Redis 由淺入深 (1) - 常用的基礎資料型別及使用場景
Redis 由淺入深 (1) - Redis常用的基礎資料型別及使用場景
前言
隨著系統的業務和使用者量的不斷的增長,傳統的單體應用(請求直查 DB)已經無法支撐大量的使用者訪問。為了提高系統的吞吐量就必須使用一些中介軟體去提升效能,而Redis就是提升吞吐量的核武器。Redis可以做分散式鎖、應用快取、註冊中心、訊息佇列(不推薦使用)、釋出訂閱、集合計算等等功能。
一、字串型別
String型別是Redis最基本的資料結構型別,是二進位制安全的,其他幾種資料結構都是在字串型別上構建的。
在專案中一般應用在簡單的鍵值快取、庫存計數。很多開發者圖簡單方便也會把物件轉換成JSON String存入Redis,取的時候也會反序列化一遍。這樣雖然說沒有什麼問題,但效能會稍微差一點,如果有存物件的需要還是儘量使用hash型別。
bash
key: biz:user:10002
value: {"name": "allens", "job": "programer", ....}
命令:
bash
set key value [ex sec] [px mills] [nx|xx]
REDIS命令參考 (http://doc.redisfans.com/index.html),可以在這份文件中查到所有redis命令的說明及細節。
二、列表
列表(list)型別是用來儲存多個有序的字串,如圖218所示,a、b、c、d、e五個元素從左到右組成了一個有序的列表,列表中的每個字串稱為元素(element),一個列表最多可以儲存2321個元素。在Redis中,可以對列表兩端插入(push)和彈出(pop),還可以獲取指定範圍的元素列表、獲取指定索引下標的元素。列表是一種比較靈活的資料結構,它可以充當棧和佇列的角色,在實際開發上有很多應用場景。
使用場景
① redis的列表可以做簡單的訊息佇列,將訊息實體轉成字串。lpush到佇列左側,然後rpop從右側彈出資料即可簡單實現一個訊息佇列。但使用rpop這種方式是非阻塞的,如果沒有訊息插入也會返回。一般使用blpop或者是brpop命令進行阻塞等待獲取到訊息,然後再根據獲取到的訊息反序列化進行處理。這種方式在併發量並不高、可以容忍丟訊息的情況下能夠使用。一般情況下不建議使用redis做訊息佇列。
② 列表還可以快取文章,比如有一個場景是首頁要預設展示10篇文章,所有的使用者沒有點選分頁或更多button之前都是預設展示這10篇文章的,就可以把這10篇文章放在快取中直接進行展示。也可以儲存更多分頁的文章,cache key 可以設計為article:1(分頁):id(文章id)。
命令:
bash
rpush key value [value...] # 從右側插入元素
lpush key value [value...] # 從左側插入元素
lindex key # 獲取指定索引下標
llen key # 獲取列表長度
lpop key # 從列表左側彈出元素
rpop key # 從列表右側彈出元素
blpop key [key ...] timeout # 阻塞獲取訊息
brpop key [key ...] timeout # 阻塞獲取訊息
三、雜湊
幾乎所有的程式語言都提供了雜湊(hash)型別,它們的叫法可能是雜湊、字典、關聯陣列。在Redis中,雜湊型別是指鍵值本身又是一個鍵值對結構,形如value={{field1,value1},...{fieldN,valueN}}。
使用場景
Hash型別可以用來session快取、快取使用者資訊、級聯分類等等,比如專案中使用Spring-data-session-redis的話,Spring將通過Spring-data-session-redis封裝的一個Filter將SpringHttpSession(tomcat servlet session)存入到redis中。獲取的話直接從redis中獲取到使用者的資訊,而不是將session存入到本地。專案本地只會快取一個sessionid其他所有的session attr 都會到redis中進行獲取。後續會有文章專門討論spring-data-session-redis的實現原理,以及注意事項。
bash
hset key field value # hset user:1 name tom
hget key field # hget user:1 name
hlen key # 計算field個數
hkeys user:1 # 獲取所有的key field
hvals key # 獲取所有的value
hget all key # 獲取的field & value
hmget
hscan
hincrby key field
hstrlen key field # 計算value的字串長度
四、集合
集合(set)型別也是用來儲存多個的字串元素,但和列表型別不一樣的是,集合中不允許有重複元素,並且集合中的元素是無序的,不能通過索引下標獲取元素。如圖222所示,集合user:1:follow包含著"it"、"music"、"his"、"sports"四個元素,一個集合最多可以儲存2321個元素。Redis除了支援集合內的增刪改查,同時還支援多個集合取交集、並集、差集,合理地使用好集合型別,能在實際開發中解決很多實際問題。
使用場景
集合可以用用在使用者的標籤或者是某種產品的標籤上,key:user:1:tag,比如很多使用者都喜歡打籃球,就可以使用集合獲取所有喜歡打籃球的人,或者是喜歡某一類產品的使用者都可以通過集合來快速分析獲取。
bash
sadd key element [element ...]
exists key
srem key element [element ...]
spop key # 隨機彈出元素
smembers key # 獲取所有元素
smembers myset
集合間操作:
```
集合1
sadd user:1:fllow it music his sports
集合2
sadd user:2:fllow it news ent sports
求交集
sinter key [key ...] sinter user:1:fllow user:2:follow
sports it
求並集
suinon key [key ...] sunion user:1:follow user:2:follow
兩個集合所有的不重複元素
差集
sdiff key [key...]
music his
```
五、有序集合
有序集合相對於雜湊、列表、集合來說會有一點點陌生,但既然叫有序集合,那麼它和集合必然有著聯絡,它保留了集合不能有重複成員的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下標作為排序依據不同的是,它給每個元素設定一個分數(score)作為排序的依據。如圖224所示,該有序集合包含kris、mike、frank、tim、martin、tom,它們的分數分別是1、91、200、220、250、251,有序集合提供了獲取指定分數和元素範圍查詢、計算成員排名等功能,合理的利用有序集合,能幫助我們在實際開發中解決很多問題。
sortedSet 可以用在排行榜系統上,比如按影片播放量排序,按點贊次數排序等等。
```bash zadd video:ranking:2016_03_15 222222(影片id) 3 zincrby video:ranking:2016_03_15 222222 1 # 增加點贊數 zrem video:ranking:2016_03_15 222222 # 從排行榜中刪除
獲取點贊最多的十條影片
zrevrangebyrank video:ranking:2016_03_15 222222 10 zscore video:ranking:2016_03_15 222222 # 獲取視屏分數 zrank video:ranking:2016_03_15 222222 # 獲取視屏排名 ``` 命令參考:http://doc.redisfans.com/index.html
六、Bitmaps
現代計算機用二進位制(位)作為資訊的基礎單位,1個位元組等於8位,例如“big”字串是由3個位元組組成,但實際在計算機儲存時將其用二進位制表示,“big”分別對應的ASCII碼分別是98、105、103,對應的二進位制分別是01100010、01101001和01100111。
Bitmaps本身不是一種資料結構,實際上它就是字串,但是他可以對字串的位進行操作。可以把Bitmaps想象成一個以位為單位的陣列,陣列的每個單元只能儲存0和1,陣列的下標在Bitmaps中叫做偏移量。
下面是使用bitmaps分析網站某個使用者訪問過的應用場景:
設定鍵的第offset個位的值(從0算起),假設現在有20個使用者,userid=0,5,11,15,19的使用者對網站進行了訪問。
setbit unique:users:2022-05-30 0 1
setbit unique:users:2022-05-30 5 1
...
很多應用的使用者id以一個指定數字(例如10000)開頭,直接將使用者id和Bitmaps的偏移量對應勢必會造成一定的浪費,通常的做法是每次做setbit操作時將使用者id減去這個指定數字。在第一次初始化Bitmaps時,假如偏移量非常大,那麼整個初始化過程執行會比較慢,可能會造成Redis的阻塞。
命令操作
bash
getbit unique:users:2022-05-30 1000000 #使用者不存在所以返回0
bigcount [start][end] # start ~ end 表示從start位元組到 end位元組範圍,查詢出在第start個位元組到第end個位元組的獨立訪問使用者數
bigcount unique:uesrs:2022-05-30 # 算出這天獨立訪問的使用者數量
bitop op destkey key[key...] # 可以計算多個bitmaps的交集並集
七、HyperLogLog
HyperLogLog並不是一種新的資料結構(實際型別為字串型別),而是一種基數演算法,通過HyperLogLog可以利用極小的記憶體空間完成獨立總數的統計,資料集可以是IP、Email、ID等。HyperLogLog提供了3個命令:pfadd、pfcount、pfmerge。
HyperLogLog的演算法連結(https://en.wikipedia.org/wiki/Philippe_Flajolet)
HyperLogLog記憶體佔用量非常小,但是存在錯誤率,開發者在進行資料結構選型時只需要確認如下兩條即可
* 只為了計算獨立總數,不需要獲取單挑資料。
* 可以容忍一定誤差率,畢竟HyperLogLog在記憶體的佔用量上有很大優勢
八、鍵管理
鍵重新命名
bash
rename key newkey
隨機返回一個鍵
bash
randomkey
鍵過期
```bash expireat pexpire pexpireat pttl persist
expire key sec # 在sec秒後鍵過期 expire at key timestemp # 在timestemp時間點,鍵過期 ttl key # 獲取過期還剩餘的時間 ```
遍歷鍵
bash
keys pattern # patter可以是具體值和正則
scan cursor [match pattern [count number]
- cursor是必需引數,實際上cursor是一個遊標,第一次遍歷從0開始,每次scan遍歷完都會返回當前遊標的值,直到遊標值為0,表示遍歷結束。
- matchpattern是可選引數,它的作用的是做模式的匹配,這點和keys的模式匹配很像。
- countnumber是可選引數,它的作用是表明每次要遍歷的鍵個數,預設值是10,此引數可以適當增大。
總結
萬丈高樓平地起,掌握好redis基礎的資料結構,要靈活應用各種資料型別來解決不同的應用場景。下一節將會講redis的安裝,以及幾種部署結構。
學習更多幹貨類容(JAVA、前端、Kafka、redis等等)請關注我的公眾號