目錄
1.Set類型
1.1 Set集合
1.2 普通命令
1.3 集合操作
1.4 內部編碼
1.5 使用場景
2.Zset類型
2.1 Zset有序集合
2.2 普通命令
2.3 集合間操作
2.4 內部編碼
2.5 使用場景
1.Set類型
1.1 Set集合
集合類型也是保存多個字符串類型的元素,但是和列表類型不同的是,集合中的元素是無序的,并且不允許重復,Redis除了支持集合內的增刪改查操作,同時還支持多個集合取交集、并集、差集
集合類型
1.2 普通命令
SADD
將一個或者多個元素添加到set中,重復的元素無法添加到set中
語法:
SADD key member [member ...]
時間復雜度:O(1)
返回值:添加成功的元素個數
SMEMBERS
獲取一個 set 中的所有元素,元素之間的順序是無序的
語法:
SMEMBERS key
時間復雜度:O(N)
返回值:所有元素的列表?
SISMEMBER
判斷一個元素在不在 set 中
語法:
SISMEMBER key member
時間復雜度:O(1)
返回值:1表示元素在 set 中,0表示不在 set 中或者 key 不存在
SCARD
獲取 set 中元素的個數
語法:
SCARD key
時間復雜度:O(1)
返回值:set 內元素的個數
SPOP
從 set 中刪除并返回一個或者多個元素,由于 set 中元素是無序的,所以取出的元素是隨機的
語法:
SPOP key [count]
count代表個數,不寫表示隨機刪除一個,寫的時候,寫幾個就刪除幾個
時間復雜度:O(N),N為count
返回值:取出的元素
SMOVE
將一個元素從源 set 取出并放入目標 set 中
語法:
SMOVE source destination member
時間復雜度:O(1)
返回值:1表示成功,0表示失敗
如果繼續給key1里面添加一個1,然后再把這個1移動到key2,smove也會按照刪除插入執行
SREM
將指定的元素從 set 中刪除
語法:
SREM key member [member ...]
時間復雜度:O(N),N為要刪除元素的個數
返回值:刪除元素的個數
1.3 集合操作
交集(inter)、并集(union)、差集(diff)
SINTER
獲取給定 set 的交集中的元素
語法:
SINTER key [key ...]
時間復雜度:O(N * M),N是最小的集合元素個數,M是最大的集合元素個數
返回值:交集的元素
SINTERSTORE
獲取給定 set 的交集中的元素并保存到目標 set 中
語法:
SINTERSTORE destination key [key ...]
時間復雜度:O(N * M),N是最小的集合元素個數,M是最大的集合元素個數
返回值:交集的元素個數
SUNION
獲取給定 set 的并集中的元素
語法:
SUNION key [key ...]
時間復雜度:O(N),N為給定所有集合的總的元素個數
返回值:并集的元素
SUNIONSTORE
獲取給定 set 的并集中的元素并保存到目標 set 中
語法:
SUNIONSTORE destination key [key ...]
時間復雜度:O(N),N為給定所有集合的總的元素個數
返回值:并集的元素個數
SDIFF
獲取給定 set 的差集中的元素
語法:
SDIFF key [key ...]
時間復雜度:O(N),N為給定的所有集合的總的元素個數
返回值:差集的元素
SDIFFSTORE
獲取給定 set 的差集中的元素并保存到目標 set 中
語法:
SDIFFSTORE destination key [key ...]
時間復雜度:O(N),N為給定的所有集合的總的元素個數
返回值:差集的元素個數
1.4 內部編碼
集合類型的內部編碼有兩種:
1)intset(整數集合):當集合中的元素都是整數并且元素格式小于?set-max-intset-entries 配置(默認512個)時,Redis會選用 intset 來作為集合的內部實現,從而減少內存的使用
2)hashtable(哈希表):當集合類型無法滿足 intset 的條件時,Redis會使用hashtable作為集合的內部實現
當元素個數較少并且都為整數時,內部編碼為 intset:
當元素不是整數時,內部編碼為 hashtable:
1.5 使用場景
1)標簽
集合類型比較典型的使用場景是標簽,例如A用戶對娛樂、體育感興趣,B用戶對游戲、綜藝感興趣,這些興趣點可以被抽象成標簽
給用戶添加標簽
sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
...
sadd user:k:tags tag1 tag2 tag4
給標簽添加用戶
sadd tag1:users user:1 user:3
sadd tag2:users user:1 user:2 user:3
...
sadd tagk:users user:1 user:4 user:9 user:28
刪除用戶下的標簽?
srem user:1:tags tag1 tag5
...
刪除標簽下的用戶
srem tag1:users user:1
srem tag5:users user:1
...
計算用戶的共同興趣標簽
sinter user:1:tags user:2:tags
2)使用 set 計算用戶之間的共同好友
對兩個用戶的好友總數取交集
3)使用 set 統計 UV
PV:表示用戶每次訪問服務器,都會產生一個PV
UV:表示每個用戶訪問服務器,都會產生一個UV,但是同一個用戶多次訪問,不會增加UV
2.Zset類型
2.1 Zset有序集合
有序集合中可以存在重復的元素,與集合不同的是,有序集合中的每個元素都有一個唯一的浮點類型的分數(score)與之關聯,使得有序集合中的元素是可以維護有序性的,在進行排序的時候就是根據分數(score)的大小來說進行升序/降序排序
列表、集合、有序集合三者的異同點
2.2 普通命令
ZADD
添加或者更新指定元素以及關聯的分數到zset中,分數應該符合double類型
NX:用于添加新元素,不會更新已經存在的元素
XX: 用于更新已經存在的元素,不會添加新元素
CH:默認情況下,ZADD返回的是本次添加元素的個數,指定這個選項之后,就會包含本次更新元素的個數
INCR:將元素的分數加上指定的分數,此時只能指定一個元素和分數
語法:
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member
...]
時間復雜度:O(logN)
返回值:本次添加成功的元素個數
注意:hash、set、list很多時候添加一個元素的時間復雜度都是O(1),由于zset是有序結構,它要為新添加的元素取尋找合適的位置,之所以是logN不是N,是因為zset內部的數據結構是跳表
實際上zset內部就是按照升序的方式來排序的,如果兩個元素的分數相同,就按照字符串的字典序來進行排序
如果修改了分數,影響了之前的順序,就會自動移動元素位置,保持升序的順序不變,此處只修改沒有添加返回值就是0
添加新的元素,此處的返回值就是1
加上ch這個選項,更新元素之后,返回值就是更新元素的個數
給元素加上指定的分數,返回值就是最終的分數,只能指定一個元素和分數
ZCARD
獲取一個zset中元素的個數
語法:
ZCARD key
時間復雜度:O(1)
返回值:zset內的元素個數
ZCOUNT
返回分數在 min 和 max 之間的元素個數,默認情況下,min 和 max 都是包含,可以通過 ( 排除
語法:
ZCOUNT key min max
時間復雜度:O(logN)
zcount先根據 min 找到對應的元素, 再根據 max 找到對應的元素,zset 會記錄每個元素當前的次序,查詢到元素,就知道了元素的次序,然后直接把 max 對應的元素和 min 對應的元素次序做減法
返回值:滿足條件的元素列表個數
包含 50 和 77
排除 50 和 77
ZRANGE
返回指定區間的元素,分數按照升序,加上 WITHSCORES 可以把分數也返回
語法:
ZRANGE key start stop [WITHSCORES]
時間復雜度:O(logN + M)
此處要根據次序(下標)找到邊界值,時間復雜度就是zcount的時間復雜度O(logN),而 M 是 start? 和 stop之間的元素個數
返回值:區間內的元素列表?
ZREVRANGE
返回指定區間的元素,分數按照降序
語法:
ZREVRANGE key start stop [WITHSCORES]
時間復雜度:O(logN)
返回值:區間內的元素列表?
ZRANGEBYSCORE
返回分數在 min 和 max 之間的元素,默認情況 min 和 max 都是包含的,可以通過 ( 排除
語法:
ZRANGEBYSCORE key min max [WITHSCORES]
時間復雜度:O(logN + M)
返回值:區間內的元素列表
ZPOPMAX
刪除并返回分數最高的 count 個元素?
語法:
ZPOPMAX key [count]
時間復雜度:O(logN * M)
N 是有序集合的元素個數,M 是要刪除元素的個數,count 不寫表示刪除一個,寫幾就刪除幾個
返回值:分數和元素列表
BZPOPMAX
ZPOPMAX 的阻塞版本?
語法:
BZPOPMAX key [key ...] timeout
時間復雜度:O(logN)
時間復雜度是 logN,是因為從 key 上面只刪除了一次元素
返回值:元素列表
ZPOPMIN
刪除并返回分數最低的 count 個元素
語法:
ZPOPMIN key [count]
時間復雜度:O(logN * M)
返回值:分數和元素列表
BZPOPMIN
ZPOPMIN的阻塞版本
語法:
BZPOPMIN key [key ...] timeout
時間復雜度:O(logN)
返回值:元素列表
ZRANK
返回指定元素的排名,升序
語法:
ZRANK key member
時間復雜度:O(logN)
返回值:排名
ZREVRANK
返回指定元素的排名,降序
語法:
ZREVRANK key member
時間復雜度:O(logN)
返回值:排名
ZSCORE
返回指定元素的分數
語法:
ZSCORE key member
時間復雜度:O(1)
返回值:分數
ZREM
刪除指定的元素
語法:
ZREM key member [member ...]
時間復雜度:O(logN * M)
N 是整個有序集合中元素個數,M 是 member 的個數
返回值:刪除元素的個數
ZREMRANGEBYRANK
按照排序,升序刪除指定范圍的元素,左閉右閉
語法:
ZREMRANGEBYRANK key start stop
時間復雜度:O(logN + M)
N 是整個有序幾個的元素個數,M 是 start - stop 區間中元素的個數,此處只需要進行一次查找
返回值:刪除元素的個數
ZREMRANGEBYSCORE
按照分數刪除指定范圍的元素,左閉右閉
語法:
ZREMRANGEBYSCORE key min max
時間復雜度:O(logN + M)
返回值:刪除元素的個數
ZINCRBY
為指定的元素加上指定的分數
語法:
ZINCRBY key increment member
時間復雜度:O(logN)
由于增加后的元素可能會改變原有的位置,此時需要保證有序集合中的元素仍然是升序的,因此時間復雜度為 logN
返回值:增加后元素的分數
2.3 集合間操作
ZINTERSTORE
求出給定有序集合中元素并保存到目標集合中,在合并過程中以元素為單位進行合格,元素對應的分數按照不同的聚合方式和權重重新得到新的分數
語法:
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight
[weight ...]] [AGGREGATE <SUM | MIN | MAX>]
destination:要把結果存儲到哪個 key 對應的 zset 中
numkeys:整數,表示有幾個 key 參與交集運算?,前面的命令中不涉及到 numkeys,此處涉及到numkeys是為了明確知道后面的選項從哪開始了(類似面向字節流的粘包問題),如果沒有這個整數,就無法知道有幾個 key 參與
weight:權重
sum: 求和? ? ? ? min:取最小? ? ? ? max:取最大
時間復雜度:O(N * K) + O(logN * M)
N是輸入的有序集合中最小的有序集合的元素個數,K表示幾個有序集合,M是最終結果的有序集合的元素個數
返回值:目標集合中的元素個數
對 key1 * 2,key2 * 3之后,再將他們相加,得到最終結果
對 key1 和 key2 求交集,取最小值
對 key1 和 key2 求交集,取最大值?
在有序集合中,member 才是元素的本體,而 score 只是輔助的,因此,在進行求交集時,只要 member相同就行
ZUNIONSTORE
求出給定有序集合中元素的并集并保存到目標有序集合中,在合并的過程中以元素為單位進行合并,元素對應的分數按照不同的聚合方式和權重得到新的分數
語法:
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight
[weight ...]] [AGGREGATE <SUM | MIN | MAX>]
時間復雜度:O(N) + O(logN * M)
N是輸入的有序集合總的元素個數,M是最終結果的有序集合的元素個數
返回值:目標集合中的元素個數
2.4 內部編碼
?1)當元素個數較少且每個元素較小時,內部編碼為 ziplist:
2)當元素個數超過128個,內部編碼為 skiplist:
127.0.0.1:6379> ZADD key2 10 kkkkkk......
2.5 使用場景
1)添加用戶贊數
例如 A 用戶發布了一篇文章,獲得了 3 個贊,此時就可以使用有序集合中的 ZADD 和 ZINCRBY
zadd user:ranking 3 A
后續再獲得贊數,可以使用 ZINCRBY 了
zincrby user:ranking 1 A
2)取消用戶贊數
如果用戶注銷,此時就可以把用戶從榜單上刪除,可以使用 ZREM
zrem user:ranking A
3) 展示用戶信息以及用戶分數
例如將用戶的信息(姓名、年齡)保存再哈希類型中,先獲取用戶的 name ,再根據 name 去查用戶的分數和排名
存儲用戶的信息
HSET user:info name A age 19
獲取用戶的信息
HGETALL user:info
此時就獲取到了用戶的 name 和 age,再根據 name 去查詢用戶的分數和排名
ZSCORE?user:ranking A
ZRANK?user:ranking A