數據類型
string類型
存儲的數據:單個數據,最簡單的數據存儲類型,也是最常用的數據存儲類型。
存儲數據的格式:一個存儲空間保存一個數據
存儲內容:通常使用字符串,如果字符串以整數的形式展示,可以作爲數字操作使用。
string基本操作
代碼 | 實現功能 |
---|---|
set key value | 設置數據 |
get key | 獲取數據 |
del key | 刪除數據 |
mset key1 value1 [key2 value2 … ] | 設置多個數據 |
mget key1 [key2 … ] | 獲取多條數據 |
strlen key | 查詢數據長度 |
append key value | 在特定的數據上追加信息(沒有就新建) |
演示一下如何使用
需要注意的一個點:
根據上圖,可以總結出一點,大量的數據進行傳輸的時候,一定要切開,分爲更少的次數進行傳輸。比如說有一億條,那麼可以切爲一百萬條,之後分一百次傳輸。
string類型的擴展操作——解決主鍵重複的問題
代碼 | 實現功能 |
---|---|
incr key | 某個鍵的值 + 1 |
incrby key increment_num | 增加某個鍵,增加多少看increment_num |
incrbyfloat key increment_num | 自增某個鍵,按照浮點類型 |
decr key | 某個鍵的值 - 1 |
decrby key decrease_num | 減少某個鍵的值,減少數量參考decrease_num |
演示樣例:
所以這個num可以當做類似於MySQL當中的increment主鍵,達到主鍵不重複的目的。
現在再分析一種情況,幾個小例子:
1、現在舉行"最強程序員"的海選活動,通過微信投票,每個微信號4小時只能投一票。
2、電商商家開啓熱門商品推薦,但是一個商品不能一直處於熱門期,一種商品只能維持三天熱度,三天後熱度自動取消。
3、熱點網站會出現熱點新聞,熱點新聞最大的特徵是時效性,怎樣自動控制熱點新聞的時效性
string類型數據的擴展操作——設置時間限制
代碼 | 實現功能 |
---|---|
setex key seconds value | 寫鍵值的時候,指定過期時間second |
psetex key milliseconds value | 寫鍵值的時候,指定過期時間millisecond(毫秒級別) |
演示樣例:
通過這樣控制數據生命週期,通過數據是否失效控制業務行爲,適用於所有具有時效性限制控制的操作上。
string數據類型的操作注意事項
1、數據操作不成功的反饋和數據正常操作的反饋之間的差異
(1)運行結果是否成功 (integer)0 ==》false | (integer) 1 ==》true 成功
(2)表示運行結果的值 (integer)num ==》 操作之後的value的長度是num
(3)nil ==》 相當於null,空值
string類型的應用場景
每次我們刷微博的時候經常會看見頁面上有很多的點贊,關注等信息,那麼如何使用redis來實現呢??
下面測試一下:redis當中存儲用戶收到的點贊量,blog數,關注的數量,以用戶、主鍵和屬性值作爲key
分析:數據格式 user🆔property_value:用戶信息
但是這樣的話,每次都得根據用戶關鍵字get很多次纔可以得到用戶的完整信息,我們想的是一次get出很多條,get出來的這些都是詳細的用戶信息。那麼json格式應該是最合適的。
使用json格式存儲用戶的信息的操作:
Redis適用的場景
適用於各種結構型和非結構性高熱度數據訪問加速。使用鍵值存儲對速度很有幫助。
關於Redis裏面key的命名慣例
表名 | 主鍵名 | 主鍵值 | 屬性名 |
---|---|---|---|
user | id | 95535 | name |
user | id | 95535 | blogs |
user | id | 95535 | fans |
Hash類型
剛纔寫的那些,字符串保存json信息雖然可以,但是看起來還是比較的笨重,但是把信息按照hash格式存儲就會簡單很多。
hash類型
- 新的需求: 對一系列存儲的數據進行編組,方便管理,典型應用存儲對象信息。
- 需要的存儲結構:一個存儲空間保存多個鍵值對數據
- hash類型:底層使用哈希結構實現數據存儲
Reids使用hash存儲空間
在hash當中的鍵值就不叫key-value了,叫做field-value了。
- 如果field的數量比較少,存儲結構優化爲類數組結構。
- 如果field的數量比較多,存儲結構就使用hashmap結構
hash類型的基本操作
命令 | 實現功能 |
---|---|
hset key field value | 設置hash類型數據 |
hget key field | 得到key裏面的域名稱的值 |
hgetall key | 得到key裏面所有的值 |
hdel key field1 [fiield2 …] | 根據key和field值刪除數據 |
操作演示:
hash類型數據擴展操作
代碼 | 實現功能 |
---|---|
hkeys key | 獲取hash表當中的字段名 |
hvalus key | 獲取hash表當中的字段值 |
hincrby key field increment_value | 增加指定字段的數值數據增加指定範圍 |
hincrbyfloat key field increment_value | 增加指定字段的數值數據增加指定的範圍 按照浮點數 |
多元操作
代碼 | 實現功能 |
---|---|
hmset key field1 value1 [field2 value2 …] | |
hmset key field1 value1 [field2 value2 …] |
hash類型數據操作的注意事項
- hash類型下的value只能存儲字符串,不允許存儲其他數據類型,不存在嵌套現象。如果數據未獲取到,對應的值爲(nil)。
- 每個hash可以存儲2的 32次冪-1 個鍵值對
- hash類型十分貼近對象的數據存儲形式,並且可以靈活添加刪除對象屬性。但hash設計初衷不是爲了存儲大量對象而設計的,切記不可濫用,更不可以將hash作爲對象列表使用
- hgetall操作可以獲取全部屬性,如果內部field過多, 遍歷整體數據效率就很會低,有可能成爲數據訪問瓶頸。
hash的一個應用場景——電商網站購物車設計和實現
每當我們打開淘寶購物的時候,頁面上都會顯示很多的信息,商品的數量,商品名稱信息,商品的總量,商品的勾選什麼的。現在使用redis來個簡單的實現,
業務分析
在這裏僅分析購物車的redis存儲模型添加、瀏覽、更改數量、刪除清空這些問題。
解決方案
1、以客戶id作爲key,每位客戶創建一個hash存儲結構存儲對應的購物車信息
2、將商品編號作爲field,購買數量作爲value進行存儲
3、添加商品:追加全新的field與value
4、瀏覽:遍歷hash
5、更改數量:自增/自減,設置value值
6、刪除商品:刪除field
7、清空:刪除key
使用redis來操作一下:
但是這樣真的是加速了購物車的實現嗎?很顯然不是,商品的基本信息還是得繼續查詢數據庫,也就是需要二次查詢。這也是浪費時間的。那麼要是繼續顯示商品信息,如何做?
這裏有一個解決方案:
就是每個商品保存兩個field,一個是商品的數量信息,一個保存商品名信息,圖片地址,商家信息,什麼的,就像是一個hash裏面又套了一個hash。field1:nums field2:info[…]
redis的hash類型還提供了一個這個方法:hsetnx key field value
,實現的功能是追加信息,如果信息存儲在,不覆蓋,直接跳過,如果不存在,就加進去。
hash類型的應用場景——客戶搶購
假設在雙十一的時候,某一商家面覅額提供30、50、100的手機充值卡若干,每種上線100張,那麼如何實現這個搶購的功能??
解決方案
1、以商家id作爲key
2、將參與搶購的商品id作爲field
3、將參與搶購的商品數量作爲對應的value
4、搶購時使用降值的方式控制產品數量
實現如下:
String(json)的實現和hash存儲對象的比較
String + json數據格式,保證數據的完整性,強調的是數據的查詢
hash儲存對象儲存的數據是分散的,強調的是數據的更新。
List類型
數據存儲需求:存儲多個數據,並對數據進入存儲空間的順序進行區分、
需要的存儲結構:一個存儲空間保存多個數據,且通過數據可以體現進入順序
list類型:保存多個數據,底層使用雙向鏈表存儲結構實現
list類型基本操作:
操作 | 實現功能 |
---|---|
lpush key value1 [value2 …] | 從鏈表的左面進入 |
rpush key value1 [value2 …] | 從鏈表的右面進入 |
lpop key | 從鏈表得左側拿出值 |
rpop key | 從鏈表得右側拿出值 |
lrange key start stop | 從左到右按順序讀取(-1)代表倒數第幾個 |
lindex key index | 從左側開始查找下標是index的元素 |
llen key | 查看鏈表的長度 |
lindex和llen
list類型的擴展操作: lrem key count value
移除指定數量的數據:(這裏是在list0當中刪除 3 個 a)
list類型數據操作注意事項
1、list中保存的數據都是string類型的,數據總容量是有限的,最多2的32次方- 1個元素(4294967295)。
2、list具有索引的概念,但是操作數據時通常以隊列的形式進行入隊出隊操作,或以棧的形式進行入棧出棧操作
3、獲取全部數據操作結束索引設置爲-1
4、list可以對數據進行分頁操作,通常第一頁的信息來自於list, 第2頁及更多的信息通過數據庫的形式加載
list的業務場景——熱點資訊展示
在twitter、新浪微博、騰訊微博中個人用戶的關注列表需要按照用戶的關注順序進行展示,粉絲列表需要將最近關注的粉絲列在前面。那麼
1、新聞、資訊類網站如何將最新的新聞或資訊按照發生的時間順序展示?
2、企業運營過程中,系統將產生出大量的運營數據,如何保障多臺服務器操作日誌的統一順序輸出?
那麼我們打開多個客戶端看看操作之後結果怎樣:
我的順序是從上到下的,所以最新的數據出現在最前面,使用list就可以反映數據插入順序。
而且不僅如此,假如說在很多的服務器上都存在日誌信息,如果我現在想得到所有的日誌信息並且按照寫入的時間先後順序進行展示,如果讓這四臺服務器進行信息同步的話,那是相當麻煩的。但是假如都放到redis裏面去,因爲redis的list的特性,這個操作就極大地簡化了。
set數據類型
1、新的存儲需求:存儲大量的數據,在查詢方面提供更高的效率
2、需要的存儲結構:能夠保存大量的數據,效的內部存儲機制,便於查詢
set的存儲結構和hash是一樣的,都是field-value組成,只不過set的value始終是空的。
set的基本操作
代碼 | 實現功能 |
---|---|
sadd key member1 [member2…] | 增加數據 |
smembers key | 查詢set當中的數值 |
srem key member1 [member2…] | 刪除數據 |
scard key | 查看key裏面有多少元素 |
sismember key member | 某個值是不是key當中的元素 |
set類型業務場景
set類型數據的擴展操作
業務場景
每位用戶首次使用今日頭條時會設置3項愛好的內容,但是後期爲了增加用戶的活躍度、興趣點,必須讓用戶對其他信息類別逐漸產生興趣,增加客戶留存度,如何實現?
業務分析
1、系統分析出各個分類的最新或最熱點信息條目並組織成set集合
2、隨機挑選其中部分信息
3、配合用戶關注信息分類中的熱點信息組織成展示的全信息集合
需要我們在所有的分類當中隨機選取一些信息並且展示給用戶,正好set提供一種隨機的操作。
set 擴展操作——隨機
代碼 | 實現功能 |
---|---|
srandmember key [count] | 隨機取出member當中的一些數據 |
spop key [count] | 隨機刪除key當中的一些數據 |
set業務場景
業務場景
脈脈爲了促進用戶間的交流,保障業務成單率的提升,需要讓每位用戶擁有大量的好友,事實上職場新人不具有更多的職場好友,如何快速爲用戶積累更多的好友?
新浪微博爲了增加用戶熱度,提高用戶留存性,需要微博用戶在關注更多的人,以此獲得更多的信息或熱門話題,如何提高用戶關注他人的總量?
QQ新用戶入網年齡越來越低,這些用戶的朋友圈交際圈非常小,往往集中在一所學校甚至一個班級中, 如何幫助用戶快速積累好友用戶帶來更多的活躍度?
微信公衆號是微信信息流通的渠道之一,增加用戶關注的公衆號成爲提高用戶活躍度的一 種方式,如何幫助用戶積累更多關注的公衆號?
美團外賣爲了提升成單量,必須幫助用戶挖掘美食需求,如何推薦給用戶最適合自己的美食?
這些所有的問題都是推薦陌生人的問題,爲了擴大交際圈,爲了擴大認知度出現的問題,涉及到的都是共有一些東西,期望得到兩個集合的並集,以此來保留用戶活躍度。
set數據類型擴展操作
代碼 | 實現功能 |
---|---|
sinter key1 [key2] | 求兩個集合的交 |
sunion key1 [key2] | 求兩個集合的並 |
sdiff key1 [key2] | 求兩個集合的差 |
sinterstore destination key1 [key2] | 求兩個集合的交,並且保存在destination集合裏 |
sunionstore destination key1 [key2] | 求兩個集合的並,並且保存在destination集合裏 |
sdiffstore destination key1 [key2] | 求兩個集合的差,並且保存在destination集合裏 |
smove source destination member | 把一個集合移動到另外一個集合當中去 |
演示樣例:
set類型數據操作的注意事項
1、set 類型不允許數據重複,如果添加的數據在set中已經存在,將只保留一份
2、set 雖然與hash的存儲結構相同,但是無法啓用hash中存儲值的空間,因爲filed對應的value是(nil)空值
set類型使用場景——不重複數據合併
就拿我們平時做項目來講。每個人對不同的文件都有着不同的操作權限,可能在這個項目當中有這個權限,但是在另外一個文件當中又有另外一個權限,這麼多的權限一般人肯定是記不住的,那麼如何來獲取權限呢?如果說用戶已經有了權限,下次再賦予權限的時候,又應該如何跳過這次授權呢?
解決方案:
1、依賴set集合數據不重複的特徵,依賴set集合hash存儲結構特徵完成數據過濾與快速查詢
2、根據用戶id獲取用戶所有角色
3、根據用戶所有角色獲取用戶所有操作權限放入set集合
演示樣例:
set應用場景——去重
公司對旗下新的網站做推廣,統計網站的PV (訪問量) ,UV (獨立訪客) ,IP (獨立IP)。
PV:網站被訪問次數,可通過刷新頁面提高訪問量
UV:網站被不同用戶訪問的次數,可通過cookie統計訪問量, 相同用戶切換IP地址, UV不變
IP:網站被不同IP地址訪問的總次數,可通過IP地址統計訪問量,相同IP不同用戶訪問, IP不變
解決方案:
1、利用set集合的數據去重特徵,記錄各種訪問數據
2、建立string類型數據, 利用incr統計日訪問量(PV)
3、建立set模型,記錄不同cookie數量(UV)
4、建立set模型,記錄不同IP數量(IP)
sort_set數據類型
1、新的存儲需求:數據排序有利於數據的有效展示,需要提供-種可以根據自身特徵進行排序的方式
2、需要的存儲結構:新的存儲模型,可以保存可排序的數據
3、sorted_set類型:在set的存儲結構基礎上添加可排序字段
sort_set數據結構圖:
他的數據結構是和set一樣的,只不過是把set沒用到的那一塊利用了起來,存放字段順序,根據這個字段進行排序。
基本命令
代碼 | 實現功能 |
---|---|
zadd key score1 member1 [score2 member2 … ] | 增加一個sort_set類型信息 |
zrange key start stop [wthscores] | 查詢從下標start到stop的所有對象 從小到大的順序 |
zrevrange key start stop [withscores] | 查詢從下標start到stop的所有對象 從大到小的順序 |
zrem key member1 [member2 … ]] | 刪除集合內數據 |
zrangebyscore key min max [withscores] [limit] | 查詢正向排序指定範圍的值 |
zrevrangebyscore key max min [withscores] | 查詢反向排序指定範圍的值 |
zremrangebyrank key start stpp | 按照下標刪除字段 |
zremragngebyscore key min max | 分數在某個範圍之內的所有字段 |
演示樣例:
按照範圍查詢和刪除的功能:
小問題:有人會注意到有withscore和limit,第一個是帶着分數一起輸出,第二個是限制刪除的個數。
sorted_ set類型數據的擴展操作
業務場景:
1、票選廣東十大傑出青年,各類綜藝選秀海選投票
2、各類資源網站TOP10 (電影,歌曲,文檔,電商,遊戲等)
3、聊天室活躍度統計
4、遊戲好友親密度
這些都是對所有參與排名的資源進行排序,就可以使用sort_set的排序的特點進行前幾名的篩選。
這裏就不演示了,上面的例子已經差不多了
擴展命令
代碼 | 實現功能 |
---|---|
zcard key | 獲取集合當中的數據個數 |
zcount key min max | 獲取指定範圍的數據個數 |
zinterstore destination numkeys key1 [key2 … ] | 集合的交操作 |
zunionstore destination numkeys key1 [key2 … ] | 集合的並操作 |
演示樣例:
Key操作
key基本操作
代碼 | 實現功能 |
---|---|
del key | 刪除指定的key |
exists key | 指定的key是否存在 |
type key | 獲取key的類型 |
我以前一直好奇,要是不知道數據庫到底有多少表,那麼豈不是相當的難管理,直到現在我才明白到底是如何查詢數據庫表的。key pattern
按照你給的字符進行篩選,原理和mysql的通配符差不多。
演示樣例:
key擴展操作(時效性控制)
代碼 | 實現功能 |
---|---|
expire key seconds | 設置有效期 單位爲秒 |
pexpire key milliseconds | 設置有效期 單位爲毫秒 |
expireat key timestamp | 設置有效期 時間是到某個時間的時間戳 |
pexpireat key milliseconds-timestamp | 設置有效期 時間是到某個時間的時間戳的毫秒形式 |
ttl key | 獲取key的有效時間 |
pttl key | 獲取key的有效時間 |
persist key | 切換key從時效性轉換爲永久性 |
演示樣例:
key擴展操作(查詢模式)
上面有key pattern
但是pattern具體是怎麼使用還沒說清楚
模式內容 | 表示含義 |
---|---|
keys * | 查詢所有的 |
keys it* | 查詢所有it 開頭的 |
keys *heima | 查詢所有前面任意字符,並且heima結尾的 |
keys ??heima | 查詢所有前面兩個字符,緊接着是heima的 |
keys users::? | user:開頭,緊跟着一個任意字符的 |
keys u[st]ser :1 | 查詢開頭是u,er:1結尾,中間是一個s或者是t的 |
演示樣例:
key其他操作
操作代碼 | 實現功能 |
---|---|
rename key newkey | 重命名 |
renamenx key newkey | 重命名 |
sort | 對所有的key排序 |
help @generic | key 操作幫助信息 |
數據庫通用操作
key的重複問題
在我們開發的過程當中,可能出現key的重複的問題,出現的情況如下
1、key是由程序員定義的
2、redis在使用過程中,伴隨着操作數據量的增加,會出現大量的數據以及對應的key
3、數據不區分種類、類別混雜在一起,極易出現重複或衝突
解決方案
1、redis爲每個服務提供有16個數據庫,編號從0到15
2、每個數據庫之間的數據相互獨立
數據庫基本操作
代碼操作 | 實現功能 |
---|---|
select index | 切換數據庫 |
quit | 退出數據庫 |
ping | 驗證數據庫連接 |
echo message | 輸出信息 |
演示樣例:
DB相關操作
操作代碼 | 實現功能 |
---|---|
move key db | 移動數據到某個數據庫 |
dbsize | 數據庫大小 |
flushdb | 刪除當前數據庫當中的內容 |
flushall | 刪除所有數據庫的內容 |
演示樣例:
flushdb
和flushall
的操作就不演示了,說不定我的數據以後還有用呢……
總結:數據庫應用的場景
Tips 2:redis控制數據的生命週期,通過數據是否失效控制業務行爲,適用於所有具有時效性限定控制的操作
Tips 3:redis應用於 各種結構型和非結構型高熱度數據訪問加速
Tips 5:redis 應用於搶購,限購類、限量發放優惠卷、激活碼等業務的數據存儲設計
Tips 8:redis應用於隨機推薦類信息檢索,例如熱點歌單推薦,熱點新聞推薦,熱賣旅遊線路,應用APP推薦,大V推薦等
Tips 9:
1、redis 應用於同類信息的關聯搜索,二度關聯搜索,深度關聯搜索
2、顯示共同關注 (一度)
3、顯示共同好友 (一度)
4、由用戶A出發, 獲取到好友用戶B的好友信息列表(一度)
5、由用戶A出發, 獲取到好友用戶B的購物清單列表(二度)
6、由用戶A出發, 獲取到好友用戶B的遊戲充值列表(二度)
Tips 10:redis 應用於同類型不重複數據的合併操作