Redis常用數據結構使用場景說明和命令示例(非常實用)

Redis常用的數據結構以及各種數據結構使用場景示例(非常實用)


1、String數據結構

SET key value
// 存入字符串鍵值對

MSET key value [key value ...]
// 批量存儲字符串鍵值對

SETNX key value
// 存入一個不存在的字符串鍵值對

GET key
// 獲取字符串鍵值

MGET key [key ...]
// 批量獲取字符串鍵值

DEL key [key ...]
// 刪除一個鍵

EXPIRE key seconds
// 設置一個key的過期時間(秒)

原子性加減命令:
INCR key
// 將key中儲存的數字值加1

DECR key
// 將key中儲存的數字值減1

INCRBY key increment
// 將key中值加上increment

DECRBY key increment
// 將key中值減去increment

--增
set mykey "test"       --為鍵設置新值,并覆蓋原有值
setex mykey 10 "hello" -- 設置指定 Key 的過期時間為10秒,在存活時間可以獲取value
mset key3 "stephen" key4 "liu" --批量設置鍵
--刪
del mykey --刪除已有鍵
--改
incr mykey      --值增加1,若該key不存在,創建key,初始值設為0,增加后結果為1
decrby mykey 5  --值減少5
--查 
exists mykey   --判斷該鍵是否存在,存在返回 1,否則返回0
get mykey      --獲取Key對應的value
mget key3 key4 --批量獲取鍵

使用場景:
1、key/value單值緩存

SET key value
GET key
商品庫存 key商品ID value商品的實際庫存

2、對象緩存

SET user:1 value(JSON格式數據)

3、分布式鎖

命令 SETNX key value
當且僅當key不存在的時候執行操作,否則不執行任何操作

SETNX produce:10001 true
// 返回1代表獲取鎖成功
// 返回0代表獲取鎖失敗
。。。執行業務操作。。。
DEL product:10001
// 執行完業務釋放鎖

SET product:10001 true ex 10 nx
// 防止程序意外終止導致死鎖

4、原子計數器

比如博客,文章有個閱讀數
只要文章被打開,我即可執行一條
INCR article:readCount:{文章ID}命令

INCR article:readCount:{文章ID}
// 每次執行一次key+1

GET article:readCount:{文章ID}
// 獲取當前key的值

5、分布式系統全局序列號

INCRBY orderId 100
// redis批量生成序列號,提升性能

問題:頻繁執行Redis命令會增加Redis機器的性能壓力,這個時候可以考慮使用批量生成,然后在服務內存里面緩存起來使用

2、Hash數據結構

Hash的常用操作:

HSET key field value
// 存儲一個哈希表key的鍵值

HSETNX key field value
// 存儲一個不存在的哈希表的key鍵值

HMSET key field value [field value ...]
// 在一個Hash表中存儲多個鍵值對

HGET key field
// 獲取哈希表key對應的field的鍵值

HMGET key field [field ...]
// 批量獲取哈希表key對應field的多個鍵值

HDEL key field [field ...]
// 批量刪除哈希表key對應的field的多個鍵值

HLEN key
// 返回哈希表key中field的數量

HGETALL key
// 返回哈希表key中所有的鍵值

HINCRBY key field increment
// 為哈希表key中field的鍵的值添加增量 increment

hset cart:{用戶id} {商品id} 1  # 添加商品

hincrby cart:{用戶id} {商品id} 1 # 增加數量

hlen cart:{用戶id} # 獲取商品總數

hdel cart:{用戶id} {商品id} # 刪除商品

hgetall cart:{用戶id} #獲取購物車所有商品

--增
hset key field1 "s"   --若字段field1不存在,創建該鍵及與其關聯的Hash, Hash中,key為field1 ,并設value為s ,若字段field1存在,則覆蓋 
hmset key field1 "hello" field2 "world" -- 一次性設置多個字段    
--刪
hdel key field1 --刪除 key 鍵中字段名為 field1 的字段
del key  -- 刪除鍵    
--改 
hincrby key field 1 --給field的值加1
--查
hget key field1 --獲取鍵值為 key,字段為 field1 的值
hlen key        --獲取key鍵的字段數量
hmget key field1 field2 field3 --一次性獲取多個字段
hgetall key --返回 key 鍵的所有field值及value值
hkeys key   --獲取key 鍵中所有字段的field值
hvals key   --獲取 key 鍵中所有字段的value值

Hash應用場景:
①對象緩存存儲命令:

HMSET user {userId}:name 張三 {userId}:balance 18

存儲數據庫對象數據,使用示例如下:
HMSET user 1:name 趙思 1:balance 180
HMSET user 2:name 王五 2:balance 190
問題:
hash最重要存儲對象數據,當某個值頻繁被修改時,非常方便。比如用戶積分,只需要操作積分的file數據即可,對象其他數據值不會受到影響

②電商購物車

1、以用戶唯一ID為哈希表的key
2、以購買商品的唯一ID為field
3、商品購買數量為value

購物車操作:HSET cert:{用于ID} {商品ID} {購買數量}
1、添加商品

HSET cert:1001 2080 1

2、增加商品數量

HINCRBY cert:1001 2080 2

3、商品總數

HLEN cert:1001

4、刪除商品

HDEL cert:1001 2080

5、獲取購物車里的所有商品

HGETALL cert:1001

注意:展示的商品詳情,通過ID去查詢然后展示數據

3、list列表數據結構

LPUSH key value [value ...]
將一個或多個值value插入到ley列表的表頭(最左邊)

RPUSH key value [value ...]
將一個或多個值value插入到ley列表的表頭(最右邊)

LPOP key
移除并返回key列表的頭元素

RPOP key
移除并返回key列表的尾元素

LRANGE key start stop
返回列表key中指定區間內的元素,區間以偏移量start和stop指定,注意從0開始

BLPOP key [key ...] timeout
從key列表的表頭彈出一個元素,所列表中沒有元素,阻塞等待timeout秒,如果timeout=0則一直阻塞等待

BRPOP key [key ...] timeout
從key列表的表尾彈出一個元素,若列表中沒有元素,阻塞等待timeout秒,如果timeout=0則一直阻塞等待


--增 
lpush mykey a b --若key不存在,創建該鍵及與其關聯的List,依次插入a ,b, 若List類型的key存在,則插入value中
rpush mykey a b --在鏈表尾部先插入b,在插入a(lpush list a b那么讀的時候是b,a的順序,而rpush是怎么放怎么讀出來
--刪
del mykey       --刪除已有鍵 
--改
lset mykey 1 e        --從頭開始, 將索引為1的元素值,設置為新值 e,若索引越界,則返回錯誤信息
--查
lrange mykey 0 -1 --取鏈表中的全部元素,其中0表示第一個元素,-1表示最后一個元素。
lrange mykey 0 2  --從頭開始,取索引為0,1,2的元素
lpop mykey        --獲取頭部元素,并且彈出頭部元素,出棧

List使用場景
常用分布式數據結構:
1、Stack棧 = LPUSH + LPOP

棧數據結構,先進后出

2、Queue隊列 = LPUSH+ RPOP

隊列數據結構,先進先出

3、Blocking MQ(阻塞隊列) = LPUSH +BPROP

注意:BPROP可以實現阻塞 B->block

4、微博,微信公眾號訂閱消息流

(幾萬以下粉絲適合)
給每個用戶,創建一個List接收消息列表,
然后發布的文章添加到用戶的List數據結構中去,同時默認是拍好序號的數據,直接使用
LRANG msg:{微博ID} 0 5
則可以取出6條數據,這樣用戶訪問的性能就很高
(注意:對于特別多訂閱用戶不適合)

超級大V,應該使用什么方案呢?

4、Set集合數據結構

Set常用操作:

SADD key member [member ...]
向集合key中存入元素。元素存在則忽略
可以批量的放元素

SREM key member [member ...]
從集合key中刪除元素

SCARD key
獲取集合key的元素個數

SISMEMBER key member
判斷member元素是否存在于集合key中

SRANDMEMBER key [count]
從集合key中選出count個元素,元素不從key中刪除

SPOP key [count]
從集合key中選出count個元素,元素從key中刪除

Set運算操作:

SINTER key [key ...]
交集運算

SINTERSTORE destination key [key...]
將交集結果存入新的集合destination中

SUNION key [key ...]
并集運算

SUNIONSTORE destination key [key ...]
將并集結果存入新的集合destination中

SDIFF key [key ...]
差集運算

SDIFFSTORE destination key [key ...]
將差集結果存入新的集合destination中

--增
sadd myset a b c --若key不存在,創建該鍵及與其關聯的set,依次插入a ,b,c。若key存在,則插入value中,若a 在myset中已經存在,則插入了 b 和 c 兩個新成員。

--刪
spop myset       --尾部的b被移出,事實上b并不是之前插入的第一個或最后一個成員
srem myset a d f --若f不存在, 移出 a、d ,并返回2

--改
smove myset myset2 a --將a從 myset 移到 myset2,

--查
sismember myset a --判斷 a 是否已經存在,返回值為 1 表示存在。
smembers myset    --查看set中的內容
scard myset       --獲取Set 集合中元素的數量
srandmember myset --隨機的返回某一成員

Set數據結構使用場景:
1、微信抽獎小程序
①點擊參與抽獎加入集合

SADD key {userID}
示例:活動act:001參與用戶2001、2002
sadd act:001 2001
sadd act:001 2002

②查看參與抽獎所有用戶

SMEMBERS key
示例:
SMEMBERS act:001
展示所有參與抽獎用戶userId

③抽取count名抽獎者

SRANDMEMBER key [count]
從集合中隨機拿出count個元素

SPOP key [count]
從集合中拿出元素并刪除元素
比如抽獎后不能再參與抽獎了

使用場景:
微信微博點贊,收藏,標簽
1、點贊

SADD like:{消息ID} {用戶ID}

2、取消點贊

SREM like:{消息ID} {用戶ID}

3、檢查用戶是否點過贊

SISMEMBER like:{消息ID} {用戶ID}

4、獲取點贊的用戶列表

SISMEMBERS like:{消息ID}

5、獲取點贊的用戶數

SCARD like:{消息ID}

關注模型:比如共同關注,你的朋友也關注了它

5、ZSet支持排序的有序集合數據結構

ZSET常用操作:

ZADD key score member [ [score member] ... ]
向有序集合key中加入帶分值的元素

ZREM key member [member ...]
從有序集合中刪除元素

ZSCORE key member
返回有序集合key中元素member的分值

ZINCRBY key increment member
為有序集合key中元素member的分值加上increment

ZCARD key
返回有序集合key中元素個數

ZRANGE key start stop [WITHSCORES]
正序獲取有序集合key從start下標到stop下標的元素

ZREVRANGE key start stop [WITHSCORES]
倒序獲取有序集合key從start下標到stop下標的元素

ZSET的集合操作:
ZUNIONSTORE destkey numkeys key [key ...]
并集計算

ZINTERSTORE destkey numkeys key [key ...]
交集計算

--增
zadd key 2 "two" 3 "three" --添加兩個分數分別是 2 和 3 的兩個成員
--刪
zrem key one two  --刪除多個成員變量,返回刪除的數量
--改
zincrby key 2 one --將成員 one 的分數增加 2,并返回該成員更新后的分數(分數改變后相應它的index也會改變)
--查 
zrange key 0 -1 WITHSCORES --返回所有成員和分數,不加WITHSCORES,只返回成員
zrange key start stop --按照元素的分值從小到大的順序返回從start 到stop之間的所有元素
zscore key three --獲取成員 three 的分數
zrangebyscore key 1 2 --獲取分數滿足表達式 1 < score <= 2 的成員
zcard key       --獲取 myzset 鍵中成員的數量
zcount key 1 2  --獲取分數滿足表達式 1 <= score <= 2 的成員的數量
zrank key member --獲取元素的排名,從小到大
zrevrank key member --獲取元素的排名,從大到小

使用場景
1、ZSET點贊按照時間排序
2、ZSET集合操作實現排行榜
①點擊新聞增加閱讀數

ZINCRBY hotNews:20220103 1 領導實地考察

②展示當日排行前十(取出ZSET前10個元素)

ZREVRANGE hotNews:20220918 0 9 WITHSCORES

③七日搜索榜單計算(求并集)

ZUNIONSTORE hotNews:202200813-202200819 7
hotsNews:202200813 hotsNews:202200814 hotsNews:202200815
hotsNews:202200816 hotsNews:202200817 hotsNews:202200818
hotsNews:202200819

④展示七日排行前十

ZREVRANGE hotNews:202200813-202200819 0 9 WITHSCORES

6、Geospatial主要存儲經緯度數據

Redis 在 3.2 推出 Geo 類型,該功能可以推算出地理位置信息,兩地之間的距離。

7、HyperLogLogs

用于大數據量基數統計,速度非常快,占用內存非常小。每個HyperLogLog鍵只需要花費12KB內存,就可以計算接近 2^64個不同元素的基數。比如計算網站UV(User view,用戶訪問數量,一個用戶一天訪問同一個URL地址多次合并為一次)。

HyperLogLog常用于大數據量的統計:
1、頁面訪問量統計或者用戶訪問量統計

2、統計注冊 IP 數

3、統計每日訪問 IP 數

4、統計頁面實時 UV 數

5、統計在線用戶數

6、統計用戶每天搜索不同詞條的個數

說明:基數不大,數據量不大就用不上,會有點大材小用浪費空間
有局限性,就是只能統計基數數量,而沒辦法去知道具體的內容是什么
bitmap相比,屬于兩種特定統計情況,簡單來說,HyperLogLog 去重比 bitmap 方便很多

一般可以bitmap和hyperloglog配合使用,bitmap標識哪些用戶活躍,hyperloglog計數

8、bitmap

1、用戶簽到
很多網站都提供了簽到功能,并且需要展示最近一個月的簽到情況,這種情況可以使用 BitMap 來實現。
根據日期 offset = (今天是一年中的第幾天) % (今年的天數),key = 年份:用戶id。

如果需要將用戶的詳細簽到信息入庫的話,可以考慮使用一個一步線程來完成。

2、統計用戶活躍數
使用日期作為 key,然后用戶 id 為 offset,如果當日活躍過就設置為1。具體怎么樣才算活躍這個標準大家可以自己指定。

假如 20201009 活躍用戶情況是: [1,0,1,1,0]
20201010 活躍用戶情況是 :[ 1,1,0,1,0 ]

統計連續兩天活躍的用戶總數:
bitop and dest1 20201009 20201010 
# dest1 中值為1的offset,就是連續兩天活躍用戶的ID
bitcount dest1

統計20201009 ~ 20201010 活躍過的用戶:
bitop or dest2 20201009 20201010 

3、統計用戶是否在線
如果需要提供一個查詢當前用戶是否在線的接口,也可以考慮使用 BitMap 。即節約空間效率又高,只需要一個 key,然后用戶 id 為 offset,如果在線就設置為 1,不在線就設置為 0。
4、實現布隆過濾器

參考鏈接:談談Redis五種數據結構及真實應用場景
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容