學以致用Redis五種數據類型總結及應用場景

Redis常用數據結構有string,hash,list,set,zset,本文將就五種數據結構常用操作進行說明,並就典型應用場景進行舉例。

1、Redis數據類型-String

String類型的數據存儲是最簡單的key-value存儲,存儲元素類型包含字符串(String)、數值(Number)、二進制(bit)三種類型。

  • 1.1、字符串(String)

  • 針對字符串常見操作:

SET key value; 存入字符串鍵
SETNX key value; 存入一個不存在的字符串,若存在key則存儲不成功
GET key;獲取一個字符串鍵
MSET key value [key value...];批量存儲字符串鍵
MGET key [key...];批量獲取字符串鍵
  • 應用場景1:分佈式全局鎖

分佈式系統對共享資源進行訪問,需要互斥來防止彼此干擾來保證一致性時,要對共享資源添加分佈式鎖。方法之一是藉助Redis setnx命令,首先執行setNX(lockObj, 1),lockObj不存在時set成功,緊接着設置過期時間expire(lockObj, 10),事務處理完畢del(lockObj)進行解鎖。另外在Redis的分佈式環境中,Redis提供了RedLock 的算法來實現一個分佈式鎖。

//獲取鎖
boolean getLock(lockObj) {
    redisUtils = getRedisConnection();
    boolean flag = redisUtils.setNX(lockObj, 1);
    if(flag) {
        expire(lockObj, 10);
    }
    return flag;
}
//釋放鎖
releaseLock(lockObj) {
    del(lockObj);
}
  • 1.2、數值(Number)
  • 針對數字常見操作:
INCRBY key increment;對數字key進行{increment}的增加
DECRBY key decrement;對數字key進行{decrement}的減少
INCR key;對數字key自增1
DECR key;對數字key自減1
  • 應用場景1:Redis實現計數器,防止刷單

計數器是Redis的原子性自增操作可實現的最直觀的模式,每當某個操作發生時向Redis發送一個INCR命令。比如在一個web應用程序中,如果想知道用戶在一年中每天的點擊量,那麼只要將用戶ID以及相關的日期信息作爲鍵,並在每次用戶點擊頁面時,執行一次自增操作即可(INCR wangpf::20200408)。防止刷單需要在接口請求上做一下併發限制的處理,或者做一個防止刷單的安全攔截,比如顯示接口請求每秒最多200次。

String redisKey = "wx_health_temp";
// 記錄接口請求次數
int count = incr(redisKey);
if (count == 1) {
    //設置1s後失效
    expire($redisKey,1);
}
//1s請求大於200次則進行攔截等待
if (count > 200) {
    return false;
}
  • 應用場景2:分佈式全局ID生成

依賴於Redis的單進程單線程模型,可以生成全局唯一的ID,用Redis的原子操作INCR和INCRBY來實現。

  • 1.3、二進制(bit)
  • 針對bits常見操作
GETBIT key offset;獲取指定偏移量上位(bit)值
SETBIT key offset value;設置或替換指定偏移量上的位(bit)值
BITCOUNT key [start] [end];統計從start到end被設置爲1的bit位的數量
  • 應用場景1:在線用戶統計

自增主鍵ID作爲bite[]數組的下標,從而可以將用戶信息和字節數據bite[]位一一對應,用戶在線則將對應位置1(SETBIT userOnline 100 1),否則置0,通過BITCOUNT userOnline統計當前在線人數。

2、Redis數據類型-Hash

Redis中Hash表存儲數據比較類似數據庫中表的一條記錄。例如存儲user表中一條數據:

HMSET user 101::teacherNo 10086 101::name wangpf 101::age 18 101::email [email protected]
  • 針對HASH操作:
HSET key field value;存儲一個散列值
HSETNX key field value;存儲一個不存在的散列值
HMSET key field value [field value...];在一個key中存儲多個field
HGET key field;獲取key field的散列鍵值
HMGET key field [field...];批量獲取key中多個field的值
HDEL key field [field...];刪除散列鍵key中field的值
  • 針對數字操作:
HINCRBY key field increment;對key散列中field進行數字操作{increment}

Hash鍵意義及不使用場景

Hash鍵意義:Hash鍵可以將信息凝聚在一起,便於管理;避免鍵名衝突、誤操作;減少內存/IO/CPU消耗。

不適合使用Hash鍵的情況:過期鍵功能的使用,過期功能只能使用在key上;二進制操作命令,如SETBIT、GETBIT;需要考慮數據量分佈的問題。

對於數據量分佈問題,這裏普及下Redis Cluster預分配Hash槽(Hash slot)相關知識:

Redis Cluster中有一個16384長度的slot槽,編號分別爲0、1、2、3……16382、16383。正常工作的時候,Redis Cluster中的每個Master節點都會負責一部分的slot槽,當有某個key被映射到某個Master負責的slot槽,那麼這個Master負責爲這個key提供服務,至於哪個Master節點負責哪個槽,這是可以由用戶指定的,也可以在初始化的時候自動生成(redis-trib.rb腳本)。在Redis Cluster中,只有Master才擁有slot槽的所有權,如果是某個Master的slave,這個slave只負責slot槽的使用,但是沒有所有權。

存儲在Redis Cluster中的所有的鍵都會被映射到這些slot槽中。數據庫中的每個鍵都屬於這16384個哈希槽的其中一個,集羣使用公式CRC16(key) % 16384來計算鍵key屬於哪個slot槽。

  • 應用場景1:服務端購物車

將購物車信息存放在Redis中,用戶唯一userID作爲key,將不同商品Hash形式存儲,HSET shoppingCar:{userID} {goodsID} {count}

3、Redis數據類型-List

List數據結構是雙向鏈表結構,可以在鏈表左右兩邊分別操作。也可以把List看成一種隊列,所以在有些場景可以用redis用作消息隊列,常見應用案例有時間軸數據、評論列表、消息傳遞等。

  • List常見操作:
LPUSH key value [value...];往key的列表鍵中左邊放入一個元素,key不存在則新建
RPUSH key value [value...];往key的列表鍵中右邊放入一個元素,key不存在則新建
LPOP key;從key的列表鍵最左端彈出一個元素,並且從List中刪除
RPOP key;從key的列表鍵最右端彈出一個元素,並且從List中刪除
LRANGE key start stop;獲取列表鍵從start下標到stop下標的元素
例如LRANGE key 0 -1;獲取key列表中所有元素
BLPOP key [key...] timeout;阻塞的從key的列表鍵最左端彈出一個元素,若列表鍵中不存在元素,阻塞等待{timeout}秒,若{timeout}=0一直阻塞
BRPOP key [key...] timeout;阻塞的從key的列表鍵最右端彈出一個元素,若列表鍵中不存在元素,阻塞等待{timeout}秒,若{timeout}=0一直阻塞
  • 應用場景1:阻塞消息隊列

藉助BLPOP和BRPOP阻塞特性,實現阻塞消息隊列。

  • 應用場景2:Pub/Sub模型

Redis通過publish和subscribe命令實現訂閱和發佈的功能。訂閱者可以通過subscribe向redis server訂閱自己感興趣的消息類型。redis將信息類型稱爲通道(channel)。當發佈者通過publish命令向redis server發送特定類型的信息時,訂閱該消息類型的全部訂閱者都會收到此消息。

Pubish username wangpf // 發佈消息
SUBSCRIBE username // 訂閱
UNSUBSCRIBE username // 取消訂閱

4、Redis數據類型-Set

利用Redis提供的Set數據結構,可以存儲一些唯一無序數據。比如在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。

  • 4.1、Set常見操作
SADD key member [member...];往集合鍵key中存放元素,若key不存在則新建
SREM key member [member...];從集合鍵key中刪除元素
SMEMBERS key;獲取集合鍵key中所有元素
SCARD key;獲取集合鍵key的元素個數
SISMEMBER key member;判斷{member}元素是否存在於集合鍵key中
SRANDMEMBER key [count];從集合鍵key中選出{count}元素,不從集合鍵中刪除
SPOP key [count];從集合鍵key中選出{count}元素,並且從集合鍵key中刪除
  • 應用場景1:點贊/簽到/打卡

用戶user0001點贊1000帖子 SADD like::1000 user0001
用戶取消點贊 SREM like::1000 user0001
檢查user0001用戶是否點贊過 SISMEMBER like::1000 user0001
獲取1000帖子點讚的用戶SMEMBERS like::1000
獲取1000帖子點贊用戶數 SCARD like::1000
  • 4.2、Set集合的運算操作
交集運算:
SINTER key [key...]
SINTERSTORE destination key [key...]
並集運算:
SUNION key [key...]
SUNIONSTORE destination key [key...]
差集運算:
SDIFF key [key...]
SDIFFSTORE destination key [key...]
  • 應用場景1:商品篩選

每個商品入庫的時候即會建立它的今天標籤列表,如品牌、屏幕尺寸、處理器、內存大小。

SADD brand::huawei  P30
SADD screenSize::5.6 P30
SADD os::android P30
SADD screenType::FHD P30

SINTER brand::huawei screenSize::5.6 os::android screentype::FHD ---> P30

5、Redis數據類型-Zset(Sorted Sets)

zset是set的一個升級版本,在set的基礎上增加了一個順序屬性(權重),這一屬性在添加修改元素的時候可以指定,每次指定後zset會自動重新按新的值調整順序。

  • Zset常見操作:
ZADD key score element [...];往有序集合鍵key中存放元素,若key不存在則新建
ZREM key element [element...];從有序集合key中刪除元素
ZSCORE key element;獲取有序集合key中{element}元素的score值
ZINCRBY key increment element;給有序集合key中{element}元素進行score值操作,若key不存在則新建,然後進行score值操作
ZCARD key;獲取有序集合key中元素個數
ZRANGE key start stop [WITHSCORES];正序獲取有序集合key從start下標到stop下標的元素
ZREVRANGE key start stop [WITHSCORES];倒序獲取有序集合key從start下標到stop下標的元素
  • 集合運算操作:
ZUNIONSTORE destkey numkeys key [key...];並集計算
ZINTERSTORE deskey numkeys key [key..];交集計算
  • 應用場景1:排行榜

ZINCREBY hotNews::20200408 1 {newsId};
ZREVRANGE hotNews::20200408 0 10 WITHSCORES

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章