redis提供了5種數據結構,理解每次數據結構的特色在開發和運維中是很重要的.使用redis版本:3.0.7javascript
本章內容以下:java
redis
列表redis
redis
集合shell
redis
有序集合數據結構
列表(list
)類型是用來存儲多個字符串,以下圖A,B,C,D
四個元素從左到右組成一個有序的集合.列表中的每一個字符串被稱爲元素(element
),一個列表最多能夠存儲(2的32次方)-1
個元素.在redis
中,能夠對列表兩端插入(push
)和彈出(pop
),還能夠獲取指定範圍的元素列表、獲取指定全部下標的元素等.app
列表類型有兩個特色:負載均衡
列表中的元素是有序的,這就意味着能夠經過索引下標獲取某個元素或者某個範圍內的元素列表.運維
列表中的元素能夠是重複的.編碼
(1) 從右邊插入元素.spa
rpush key value [value...]
例:
向列表插入a,b,c
三個元素.
lrange key 0 -1
命令能夠獲取列表中全部的元素.
(2) 從左邊插入元素.
使用方法與rpush
同樣,從左側插入.
lpush key value [value....]
例:
(1) 查詢指定範圍內的元素列表
lrange key start end
lrange
操做會獲取列表指定索引範圍全部的元素.索引下標有兩個特色:第一,索引下標從左到右分別是0
到N-1
,可是從右到左分別是-1
到-N
.第二,lrange
中的end
選項包含了自身.
例:
(2) 獲取列表指定索引下的元素
lindex key index
例:
(3) 獲取列表長度
llen key
例:
(1) 從列表左側或右側彈出元素.
以下操做是將列表最左側與右側的元素彈出來.
(2) 刪除指定元素
lrem key count value
lrem
命令會從列表中找到等於value
的元素進行刪除,根據count
的不一樣分爲三種:
count>0
,從列表中刪除指定數量(count
)的元素.
count<0
,從列表中刪除count
絕對值數量的元素.
count=0
,刪除全部.
例:
指定元素數量:
全部元素:
(3) 按照索引範圍修剪列表
ltrim key start end
例如,下面操做會保留列表第二個到第六個元素:
修改指定索引下標的元素:
lset key index value
例:
修改第一個元素的值爲c
.
阻塞式彈出:
blpop key [key...] timeout brpop key [key...] timeout
blpop
與brpop
命令是lpop
和rpop
命令的阻塞版本,他除了彈出方向不一樣,使用方法基本相同,因此下面以brpop
命令進行說明,brpop
命令包含兩個參數:
key [key...]
:多個列表的鍵.
timeout
:阻塞時間(單位爲秒
).
1)列表爲空:若是timeout
等於3
,那麼客戶端等到三秒後返回,若是timeout=0
,那麼客戶端將一直阻塞,直到彈出成功.
2)列表不爲空:客戶端會馬上返回.
在使用阻塞彈出命令時,有兩點須要注意.
第一點:若是是多個鍵,那麼會從左到右遍歷鍵,一旦有一個鍵能彈出元素客戶端就會馬上返回.
第二點:若是多個客戶端同時對一個鍵進行操做,那麼最早執行命令的客戶端能夠獲取到值.
列表類型的內部編碼有兩種:
編碼名 | 編碼描述 |
---|---|
ziplist (壓縮列表) |
當列表的元素個數大於list-max-ziplist-entries 配置(默認爲512個),同時列表中每一個元素的長度小於list-max-ziplist-value 配置(默認爲64字節). |
linkedlist (鏈表) |
當列表的長度或值得大小不知足ziplist 的要求,redis 會採用linkedlist 爲列表的內部實現編碼. |
消息隊列:redis
的lpush-brpop
命令組合便可實現阻塞隊列,生產者客戶端使用lpush
命令向列表插入元素.消費者客戶端使用brpop
命令阻塞式的"搶"列表中的尾部元素.多個客戶端保證消息的負載均衡與可用性.
文章列表:每一個用戶都有屬於本身的文章列表.此時能夠考慮使用列表,由於列表不可是有序的,同時支持使用lrange
按照索引範圍獲取多個元素.
僞代碼:
var articles = redis.lrange('user:1:acticles',0,9); articles.forEach(function(){ // 遍歷操做 });
開發提示:列表的使用場景有不少如:
lpush
+lpop
=Stack
(棧)、lpush
+rpop
=queue
(隊列)、lpush
+brpop
=message queue
(消息隊列)、lpush
+ltrim
=Capped Collection
(有限集合)
集合(set
)類型也是用來保存多個的字符串元素,但和列表不一樣的是:它的元素是無序且不可重複的,不能經過索引獲取元素.以下圖,集合user:1:follows
中包含着"his"、"it"、"sports"、"music"四個元素,一個集合最多能夠存儲(2的32次方-1)個元素.
(1) 添加元素
sadd key value [value...]
返回結果爲添加成功的元素數量.
例:
(2) 刪除元素
srem key value [value...]
返回結果爲刪除成功的元素數量.
例:
(3) 獲取元素個數
scard key
例:
(4) 判斷元素是否在集合中
sismember key value
若是元素存在於集合內則返回1
,反之返回0
.
例:
(5) 隨機從集合中返回指定個數元素
srandmember key [count]
[count]
是可選參數,若是不寫默認爲:1
.
例:
(6) 從集合中隨機彈出元素
spop key
spop操做能夠從集合中隨機彈出一個元素.
例:
使用spop
命令後,集合元素變爲"1","3".
(7) 獲取集合的全部元素
smembers key
獲取集合全部元素,且返回結果是無序的.
(1) 求多個集合的交集
sinter key [key...]
例:
(2) 求多個集合的並集
sunion key [key...]
例:
(3) 求多個集合的差集
sdiff key [key...]
例:
(4) 將交集、並集、差集的結果保存.
sinterstore storeKey key [key...] sunionstore storeKey key [key...] sdiffstore storeKey key [key...]
集合間的運算在元素比較多的狀況下會比較耗時,因此redis
提供了上面三個命令(原命令+store
)將集合間交集、並集、差集的結果保存到storeKey
中,例如將user:1:follows
和user:2:follows
兩個集合之間的交集結果保存到user:1_2:follows
中.
集合類型的內部編碼有兩種:
編碼名 | 編碼描述 |
---|---|
intset (整數集合) |
當集合中的元素全是整數,且長度不超過set-max-intset-entries (默認爲512 個)時,redis 會選用intset 做爲內部編碼. |
hashtable (哈希表) |
當集合沒法知足intset 的條件時,redis 會使用hashtable 做爲內部編碼. |
集合類型比較典型的使用場景是標籤(tag
).例如一個用戶可能對音樂感興趣,另外一個用戶對新聞感興趣,這些想去點就是標籤.有了這些數據就能夠得到喜歡同一個標籤的人,以及用戶的共同喜愛的標籤,這些數據對於用戶體驗來講比較重要.
下面使用集合類型實現標籤功能的若干功能.例如:
(1) 給用戶添加標籤:
(2) 給標籤添加用戶:
(3) 刪除用戶的標籤:
(4) 刪除標籤的用戶:3
到4
最好在同一個事務下進行處理.
(5) 計算用戶共同擁有的標籤:
有序集合相對於哈希、列表、集合來講會有一點陌生,但既然叫有序集合.那麼它和集合必然是有着聯繫,它保留了集合不能重複元素的特性.但不一樣的是,有序集合是可排序的.可是他和列表使用索引下標進行排序依據不一樣的是,它給每一個元素設置一個分數(score
)做爲排序的依據.
列表、集合、有序結合的異同點
數據結構 | 是否容許重複元素 | 是否有序 | 有序實現方式 | 應用場景 |
---|---|---|---|---|
集合 | 否 | 否 | 無 | 標籤、社交等. |
有序集合 | 否 | 是 | 分值 | 排行榜、社交等. |
列表 | 是 | 是 | 索引下標 | 時間軸、消息隊列等. |
(1) 添加成員
zadd key score member [score member ...]
下面操做向有序集合user:ranking
增長用戶Rico
和他的分數60
分:
有關zadd
命令有兩點須要注意:
Redis 3.2
爲zadd
命令添加了nx
、xx
、ch
、incr
四個選項:
nx
:member
必須不存在,才能夠設置成功,用於添加.
xx
:member
必須存在,才能夠設置成功,用於添加.
ch
:返回這次操做後,有序結合元素和分數發生變化的個數.
incr
: 對score
進行添加操做,至關於後面介紹的zincrby
.
有序集合相比集合提供了排序字段,可是也產生了代價,zadd
的時間複雜度是O(log(n))
,sadd
的時間複雜度爲O(1)
.
(2) 獲取成員個數
zcard key
例:
(3) 獲取某個成員的分數
zscore key member
例:
(4) 獲取成員排名
zrank key member zrevrank key member
zrank
命令是從分數從低到高返回排名,zrevrank
反之,排名從0
開始.例以下面:
(5) 刪除成員
zrem key member [member...]
下面操做成員ann
從有序集合user:ranking
中刪除.
(6) 增長成員分數
zincrby key score member
下面操做給Rico
成員添加9
分,分數變爲69
分.
(7) 獲取制定範圍的元素
zrange key start end [withscores] zrevrange key start end [withscores]
有序集合是按照分值排名的,zrange
是由低到高返回,zrevrange
反之,查詢所有:zrange user:ranking 0 -1
,加上withscores
參數顯示分數.
例:
獲取前三名.
127.0.0.1:6379> zrange user:ranking 0 2 1) "codger" 2) "hank" 3) "ann" 127.0.0.1:6379> zrevrange user:ranking 0 2 1) "tom" 2) "Rico" 3) "ann"
(8) 返回指定分數範圍的成員
zrangebyscore key min max [withscores] [limit offset count] zrevrangebyscore key min max [withscores] [limit offset count]
例:
返回分數在0
到100
的成員.
127.0.0.1:6379> zrangebyscore user:ranking 0 100 1) "codger" 2) "hank" 3) "ann" 4) "Rico" 5) "tom"
返回分數在0
到無限大的成員.
127.0.0.1:6379> zrangebyscore user:ranking 0 +inf 1) "codger" 2) "hank" 3) "ann" 4) "Rico" 5) "tom"
同時min
和max
還支持開區間(小括號)和閉區間(中括號),-inf
和+inf
分別表明無限小和無限大:
127.0.0.1:6379> zrangebyscore user:ranking (10 +inf withscores 1) "hank" 2) "15" 3) "ann" 4) "30" 5) "Rico" 6) "69" 7) "tom" 8) "80"
(9) 返回指定分數範圍成員個數
zcount key min max
下面返回分數爲10
到15
的成員:
127.0.0.1:6379> zcount user:ranking (10 15 (integer) 1
(10) 刪除指定排名內的升序元素
zremrangebyrank key start end
刪除第start
到第end
名的成員:
127.0.0.1:6379> zremrangebyrank user:ranking 0 1 (integer) 2
(11) 刪除指定分數範圍的成員
zremrangebyscore key min max
刪除分數從min
到max
的成員:
127.0.0.1:6379> zremrangebyscore user:ranking 0 30 (integer) 1
(1) 交集
zinterstore storeKey keyNum key [key ...] [weights weight [weight...]] [aggregate sum|min|max]
參數說明:
storeKey
:交集計算結果保存到這個鍵下.
keyNum
:須要作交集的鍵的個數.
key[key ...]
:須要作交集的鍵.
weights weight [weight...]
:每一個鍵的權重,在作交集計算時,每一個鍵中的每一個member
的分值會和這個權重相乘,每一個鍵的權重默認爲1
.
aggregate sum|min|sum
:計算成員交集後,分值能夠按照sum
(和)、min
(最小值)、max
(最大值)作彙總.默認值爲sum
.
127.0.0.1:6379> zrange user:ranking:2 0 -1 withscores 1) "Rico" 2) "138" 3) "tom" 4) "160" 127.0.0.1:6379> zinterstore user:ranking:1_2 2 user:ranking user:ranking:2 aggregate min (integer) 2 127.0.0.1:6379> zrange user:ranking:1_2 0 -1 1) "Rico" 2) "tom" 127.0.0.1:6379> zrange user:ranking:1_2 0 -1 withscores 1) "Rico" 2) "69" 3) "tom" 4) "80"
(2) 並集
zunionstore storeKey keyNum key [key...] [weights weight [weight...]] [aggregate sum|min|max]
該命令的全部參數和zinterstore
是一致的,只不過作的是並集計算.
例:
127.0.0.1:6379> zunionstore user:ranking:1_2 2 user:ranking user:ranking:2 aggregate min (integer) 3 127.0.0.1:6379> zrange user:ranking:1_2 0 -1 withscores 1) "Rico" 2) "69" 3) "codger" 4) "90" 5) "tom" 6) "160"
編碼名稱 | 編碼描述 |
---|---|
ziplist (壓縮列表) |
當有序集合的元素小於zset-max-ziplist-entries 配置(默認是128個),同時每一個元素的值都小於zset-max-ziplist-value (默認是64字節)時,Redis 會用ziplist 來做爲有序集合的內部編碼實現,ziplist 能夠有效的減小內存的使用 |
skiplist (跳躍表) |
當ziplist 的條件不知足時,有序集合將使用skiplist 做爲內部編碼的實現,來解決此時ziplist 形成的讀寫效率降低的問題. |