Redis 由淺入深 (1) - 常用的基礎資料型別及使用場景

語言: CN / TW / HK

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等等)請關注我的公眾號 網際網路技術專欄