Redis多種數據類型以及使用場景


小結

  • 字符串內部編碼:int embstr raw,用途:緩存。

  • 哈希內部編碼:壓縮ziplist hashtable

  • 列表內部編碼:壓縮ziplist linkedlist,用途:消息隊列。

  • 集合內部編碼:intset hashtable,用途:標簽,計算用戶共同感興趣的標簽。sinter user:1:tags user:2:tags

  • 有序集合內部編碼:壓縮ziplist 跳躍表zskiplist,用途:熱評的排行榜。zrevrangebyrank user:ranking:2016_0315 0 9

  • Bitmaps用途:通過極小空間進行位運算實現對狀態的判斷,例如可以做一個答題瓜分獎勵的活動,每個用戶答題答對可以設置
    setbit user 1 1,然后后用bitcount統計有多少個1,看用戶答對了多少題。

跳躍表

跳躍表支持平均OlogN、最壞ON復雜度的節點查找。

在大部分情況下,跳躍表的效率可以和平衡樹相媲美,Redis使用跳躍表作為有序集合的底層實現之一。

實現

由redis.h/zskiplistNode和redis.h/zskiplist兩個結構定義,zskiplistNode表示跳躍表節點,而zskiplist保存跳躍表

節點的相關信息,比如節點數量,以及表頭節點和表尾結點的指針。

zskiplist結構:頭結點header,尾結點tail,層數level,長度length。

zskiplistNode結構:層level(層中有前進指針和跨度),后退指針backwrad,分值score,成員對象obj。

SDS簡單動態字符串

struct sdshdr {

// 記錄buf數組中已使用字節的數量

// 等於SDS所保存字符串的長度

int len;

// 記錄buf數組中未使用字節的數量

int free;

// 字節數組,用於保存字符串

char buf[];

}

image

  • free表示這個SDS沒有分配 未使用空間。

  • len表示SDS保存了無字節長的字符串。

  • buf是一個char數組。

SDS與C字符串區別

  1. O(1)復雜度獲取字符串長度。

  2. 防止緩沖區溢出。

  3. 減少修改字符串時帶來的內存重分配次數。

字符串

命令

set key value [ex seconds] [px milliseconds] [nx|xx]

內部編碼

字符串類型的內部編碼有3種:

  • int:8個字節長整型。

  • embstr:小於等於39個字節的字符串。

  • raw:大於39個字節的字符串。

Redis會根據當前值的類型和長度決定使用哪種內部編碼實現。

整數:

set key 8653

ok

object encoding key

"int"

短字符:

set key "hello"

ok

object encoding key

"embstr"

長字符:

set key "40 bytes"

ok

object encoding key

"raw"

使用場景

  1. 緩存

  2. 計數

  3. Session集中管理

  4. 限速

哈希

命令

hset key field value

hset uset:1 name tom

hget key field

hget uset:1 name

"tom"

內部編碼

  • ziplist(壓縮列表):哈希類型元素個數小於hash-max-ziplist-entries默認512個、同時所有值都小於hash-max-

ziplist-value配置時,Redis會使用ziplist實現,節省內存方面比hashtable優秀。

  • hashtable:哈希類型無法滿足ziplist條件時,會用這個,hashtable的讀寫時間復雜度都是O(1)。

hset hashkey f3 "bigger than 64 bytes"

object encoding hashkey

"hashtable"

hmset hashkey f1 v1 f2 v2 f3 v3 ...... f513 v513

object encoding hashkey

"hashtable"

列表

從右邊插入元素:rpush key value

lrange listkey 0 -1

從左邊插入元素:lpush key value

linsert key before | after pivot value

查找:lrange key start end

刪除:lpop key

內部編碼

  • ziplist:元素個數小於list-max-ziplist-entries,同時每個值都小於list-max-ziplist-value,Redis選用壓縮列表減少內存。

  • linkedlist:無法滿足ziplist就會用鏈表來實現。

使用場景

  1. 消息隊列

  2. 文章列表

集合

用來保存多個的字符串元素,不允許重復元素,無序。

sadd key a b c 添加key

3

srem key a b 刪除key

2

scard key 計算key

1

smembers key 獲取所有元素

sinter key 求交集

suinon key 求並集

sdiff key 求差集

內部編碼

  • intset(整數集合)

  • hashtable

使用場景

標簽(tag)

給用戶添加標簽

sadd user:1:tags tag1 tag2 tag3

sadd uset:1:tags tag1 tag2 tag3

給標簽添加用戶

sadd tag1:users user:1 user:3

sadd tag2:users user:1 user:2

計算用戶共同感興趣的標簽

sinter user:1:tag2 user:2:tag

有序集合

不能重復,可以排序的set,給每個元素設置了一個score作為排序的依據。

列表、集合和有序集合三者異同點

image

命令

zadd key score member 添加成員

zadd user:ranking 251 tom

有序集合提供排序字段,產生代價,zadd復雜度為Ologn,sadd為O1。

zcard user:ranking 計算成員數

zscore key member 返回某個成員分數

zrank key member 計算成員的排名

zrem key member 刪除成員

zrange ...

集合間的操作

(1)交集

(2)並集

內部編碼

  • 壓縮列表

  • 跳躍表

使用場景

添加用戶贊數:

zadd user:ranking:2016_03_15 mike 3

獲得贊后:

zincrby user:ranking:2016_03_15 mike 1

取消贊:

zrem

獲取贊數最多的十個用戶:

zrevrangebyrank user:ranking:2016_0315 0 9

展示用戶信息以及用戶分數:

此功能將用戶名作為鍵后綴,將用戶信息保存在哈希類型中,至於用戶的分數和排名可以使用zscore和zrank

hgetall user:info:tom

zscore user:ranking:2016_03_15 mike

zrank user:ranking:2016_03_15 mike

Bitmaps

Bitmap通常被用來在極小空間消耗下通過位的運算(AND/OR/XOR/NOT)實現對狀態的判斷,常見的使用場景例如:“答對12道題的同學有機會瓜分獎池”,這種如果使用bitmap來實現,就非常容易判斷出用戶是否全部答對。

image

答題系統設計如下:

  1. 每個用戶每輪答題,設置一個key,比如user1在第一輪答題的key是 round:1:user1。
  2. 每答對一道題,設置相關的bit為1,比如user1答對了第5題,那么就設置第5個bit為1就可以了,如:SETBIT round:1:user1 5 1 ;如果用戶1在第一輪答對了第9題,那么就把第9個bit設置為1,SETBIT round:1:user1 9 1;值得注意的是,Bitmaps默認bit都是0,答錯可以不設置。
  3. 計算用戶總共答對了幾道題,就可以使用 BITCOUNT 命令統計1的bit個數。

可見,Redis的bitmap接口可以用非常高的存儲效率和計算加速效果。

待更新:

HyperLogLog

GEO

Reference

《Redis設計與實現》

《Redis開發與運維》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM