關於Redis資料型別以及應用場景的分析與總結

奕鵬發表於2021-01-18

資料型別

Redis常用的有五種型別,結合其他型別差不多有如下幾種,String、hash、list、set、zset、geo、bitmaps、hyperLogLog和Stream。

String型別

String型別是一種字串型別,類似一種鍵值對的形式。

一般我們用String型別用來儲存商品數量、使用者資訊和分散式鎖等應用場景。

1.儲存商品數量。

set goods:count:1 1233
set goods:count:2 100

2.使用者資訊。

set user:1 "{"id":1, "name":"張三", "age": 12}"
set user:2 "{"id":2, "name":"李四", "age": 12}"

3.分散式鎖。

# 設定一個不存在的鍵名為id:1值為10, 過期時間為10秒。
127.0.0.1:6379> set id:1 10 ex 10 nx
OK
127.0.0.1:6379> get id:1
"10"
# 當前的鍵還未過期,在次設定則不會設定成功。
127.0.0.1:6379> set id:1 10 ex 10 nx
(nil)
# 當10秒之後去獲取,當前的鍵則為空。
127.0.0.1:6379> get id:1
(nil)

用Redis實現分散式鎖的原理,當一個鍵存在則設定失敗。

hash型別

hash型別是一種類似關係型資料庫結構的資料結構。有一個鍵名,鍵存的內容是以鍵值對的形式存在。

利用hash結構,我們可以用來儲存使用者資訊、物件資訊等業務場景。

1.存使用者資訊。

127.0.0.1:6379> hset user:1 id 1 name zhangsan age 12 sex 1
(integer) 4
127.0.0.1:6379> hset user:2 id 2 name lisi age 14 sex 0
(integer) 4
127.0.0.1:6379> hmget user:1 id name age sex
1) "1"
2) "zhangsan"
3) "12"
4) "1"

2.儲存物件資訊。

127.0.0.1:6379> hset object:user id public-1 name private-zhangsan
(integer) 2
127.0.0.1:6379> hmget object:uesr id name
1) (nil)
2) (nil)
127.0.0.1:6379> hget object:user id
"public-1"
127.0.0.1:6379>

這裡儲存一個user物件,物件裡面有兩個屬性,分別是id和name字,分別儲存的是屬性的訪問許可權和預設值拼接。

list型別

list型別是一個列表型別的資料結構。用一個鍵,按照順序排列資料。

list一般用在的場景是佇列、棧和秒殺等場景。

1.佇列。

127.0.0.1:6379> lpush list:1 0 1 2 3 4 5 6
(integer) 7
127.0.0.1:6379> rpop list:1 1
1) "0"
127.0.0.1:6379> rpop list:1 1
1) "1"
127.0.0.1:6379> rpop list:1 1
1) "2"

使用list實現佇列,是因為佇列遵循先進先出的特點。

2.棧。

127.0.0.1:6379> lpush list:1 3 4 5 6
(integer) 3
127.0.0.1:6379> lpop list:1
"6"
127.0.0.1:6379> lpop list:1
"5"
127.0.0.1:6379> lpop list:1
"4"
127.0.0.1:6379> lpop list:1
"3"

使用list實現佇列,是因為佇列遵循後進先出的特點。

3.秒殺。

127.0.0.1:6379> lpush order:user 11 12 14 15 16 17
(integer) 6

在秒殺場景下,我們可以將秒殺成功的使用者先寫進佇列,後續的業務在根據佇列中資料進行處理。

set型別

zet是一種集合型別,並且這種集合內的元素是無需且不會重複的。

set型別一般可以用在使用者簽到、網站訪問統計、使用者關注標籤、好友推薦、猜獎、隨機數生成等業務場景。

1.某日使用者簽到情況。

127.0.0.1:6379> sadd sign:2020-01-16 1 2 3 4 5 6 7 8
(integer) 8
127.0.0.1:6379> smembers sign:2020-01-16
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"

鍵為具體某日,儲存的值則是簽到使用者的id。

2.使用者關注標籤。

127.0.0.1:6379> sadd user:1:friend 1 2 3 4 5 6
(integer) 6
127.0.0.1:6379> sadd user:2:friend 11 22 7 4 5 6
(integer) 6
127.0.0.1:6379> sinterstore user:relation user:1:friend user:2:friend
(integer) 3
127.0.0.1:6379> smembers user:relation
1) "4"
2) "5"
3) "6"

使用者1關注了id為1,2,3,4,5,6的欄目。使用者2關注了id為11,22,7,4,5,6的欄目。這裡取兩個使用者共同關注的欄目。

3.猜獎。

127.0.0.1:6379> spop user:2:friend 1
1) "5"

用set實現猜獎,主要是使用了隨機丟擲集合類的元素的特點。

zset型別

zset型別和set型別都是屬於集合型別,兩者不同點,在設定zset資料時要設定一個分數,這個分數可以用來做資料排序,並且zset型別的資料是有序的,因此zset也被叫做有序集合。

zset除了可以用在set可以用的場景下,更多的是可以用在排序的場景,如排行榜、延遲佇列,就像未支付的訂單在多少時間內就失效。

1.簽到排行榜。

127.0.0.1:6379> zadd goods:order 1610812987 1
(integer) 1
127.0.0.1:6379> zadd goods:order 1610812980 2
(integer) 1
127.0.0.1:6379> zadd goods:order 1610812950 3
(integer) 1
127.0.0.1:6379> zadd goods:order 1610814950 4
(integer) 1
127.0.0.1:6379> zcard goods:order
(integer) 4
127.0.0.1:6379> zrangebyscore goods:order 1610812950 1610812987
1) "3"
2) "2"
3) "1"

將使用者的簽到時間作為排行的分數,最後查詢指定範圍內簽到使用者的id。

Bitmaps型別

Bitmaps底層儲存的是一種二進位制格式的資料。在一些特定場景下,用該型別能夠極大的減少儲存空間,因為儲存的資料只能是0和1。為了便於理解,可以將這種資料格式理解為一個陣列的形式儲存。

利用該特點,可以將該型別用在一些訪問統計、簽到統計等場景。

1.某個使用者一個月的簽到記錄。

127.0.0.1:6379> setbit user:2020-01 0 1
(integer) 0
127.0.0.1:6379> setbit user:2020-01 1 1
(integer) 0
127.0.0.1:6379> setbit user:2020-01 2 1
(integer) 0
127.0.0.1:6379> bitcount user:2020-01 0 4
(integer) 3

統計出該使用者這個月只有4天簽到。

2.統計某一天網站的簽到數量。

127.0.0.1:6379> setbit site:2020-01-17 1 1
(integer) 0
127.0.0.1:6379> setbit site:2020-01-17 3 1
(integer) 0
127.0.0.1:6379> setbit site:2020-01-17 4 1
(integer) 0
127.0.0.1:6379> setbit site:2020-01-17 6 1
(integer) 0
127.0.0.1:6379> bitcount site:2020-01-17 0 100
(integer) 4
127.0.0.1:6379> getbit site:2020-01-17 5
(integer) 0

這裡將使用者的id作為偏移量,簽到就是1。可以統計出具體訪問的總數,同時可以根據某個使用者的id查詢是否在當前簽到。如果根據偏移量重複設定一個值,此時不會被重複新增,只是Redis會返回1表示當前已經存在。

3.計算某段時間內,都簽到的使用者數量。

127.0.0.1:6379> setbit site:2020-01-18 6 1
(integer) 0
127.0.0.1:6379> setbit site:2020-01-18 4 1
(integer) 0
127.0.0.1:6379> setbit site:2020-01-18 7 1
(integer) 0
127.0.0.1:6379> bitop and continue:site site:2020-01-18 site:2020-01-17
(integer) 1

使用該場景,是因為該資料型別可以計算出多個key的交集(and)。同時可以取並集(or),或(or),異或(xor)。

HypefLogLog型別

HypefLogLog型別從使用上來說,有點類似於集合型別。該型別實際是一種字串型別的資料結構。使用該型別最大的好處就是減少空間、但是也存在一定的誤差率。該型別也是不允許同一個key存在重複元素。該型別也支援合併多個key的值。

該資料型別一般用在一些不需要精確計算的統計類場景。

1.使用者簽到統計。

127.0.0.1:6379> pfadd 2020:01:sgin  1 2 3 4 5 6 7 8
(integer) 1
# 嘗試重複新增
127.0.0.1:6379> pfadd 2020:02:sgin  1 2 3 4 5 6 7 8
(integer) 0
127.0.0.1:6379> pfadd 2020:02:sgin  9
(integer) 1
127.0.0.1:6379> pfadd 2020:02:sgin  10
(integer) 1
127.0.0.1:6379> pfadd 2020:02:sgin  11
(integer) 1
127.0.0.1:6379> pfcount 2020:02:sgin
(integer) 11

GEO型別

GEO型別是一種儲存地理資訊的資料格式,基於該資料特點。可以用在一些距離計算、附近推薦等業務場景。

1.距離計算

127.0.0.1:6379> geoadd city:distance nx 121.32 42.36 beijing 121.20 38.56 
shanghai 100.36 38.56 sichuan
(integer) 3
127.0.0.1:6379> geopos city:distance beijing shanghai sichuan
1) 1) "121.32000178098678589"
   2) "42.36000020595371751"
2) 1) "121.19999974966049194"
   2) "38.55999947301710762"
3) 1) "100.3599974513053894"
   2) "38.55999947301710762"
# 計算出北京到上海的距離
127.0.0.1:6379> geodist city:distance beijing shanghai km
"422.7819"

Stream型別

Stream型別是Redis在5.0之後版本新增的一種資料結構。該資料結構主要使用者訊息佇列的場景。Redis 本身是有一個 Redis 釋出訂閱 (pub/sub) 來實現訊息佇列的功能,但它有個缺點就是訊息無法持久化,如果出現網路斷開、Redis 當機等,訊息就會被丟棄。

  1. 訊息佇列
    ```redis
  2. 0.0.1:6379> xadd message * name zhangsan age 12
    “1610873104343-0”
  3. 0.0.1:6379> xrange message - +
    1) 1) “1610873104343-0”
    2) 1) “name”
    2) “zhangsan”
    3) “age”
    4) “12”
  4. 0.0.1:6379> xrevrange message + - count 1
    1) 1) “1610873104343-0”
    2) 1) “name”
    2) “zhangsan”
    3) “age”
    4) “12”
    ```
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章