redis存儲任何類型的數據都是以key-value形式保存,并且所有的key都是字符串,所以討論基礎數據結構都是基于value的數據類型
?
?
常見的5種數據類型是:String、List、Set、Zset、Hash
?
?
?
?
?
一) 字符串(String)
String是redis最基本的類型,value最大是512M,String類型是二進制安全的,可以包含任何數據,如jpg圖片或者序列化的對象
?
1 使用場景
1) 緩存:redis作為緩存層,mysql做持久化層,降低mysql的讀寫壓力
?
2) 計數器:redis是單線程模型,一個命令執行完才會執行下一個,同時數據可以一步落地到其他的數據源
?
3) 分布式session
?
4) 分布式鎖
?
5) 限流
?
?
?
2 編碼
String類型的編碼包括:
?
1) int編碼:保存用 long 類型的整數值
?
2) embstr編碼:長度小于44Byte的短字符串(redis3.2版本之前是39Byte,之后是44Byte),對其進行修改后變成raw編碼,無論是否達到44字節
?
3) raw編碼: 長度大于44Byte的長字符串(redis3.2版本之前是39Byte,之后是44Byte)
?
?
?
3 編碼轉換
1) int 編碼的值不再是整數,或大小超過了long類型的時,自動轉化為raw
2) 由于redis沒有對embstr編碼的值提供修改方法(embstr編碼是只讀的),在修改embstr編碼的值時,都會先轉化為raw編碼再進行修改,修改后的對象一定是raw編碼的,無論是否達到了44Byte
?
?
?
?
?
二) List(列表)
redis中的List其實就是雙端鏈表
?
?
使用List的技巧
lpush+lpop=Stack(棧)
lpush+rpop=Queue(隊列)
lpush+ltrim=Capped Collection(有限集合)
lpush+brpop=Message Queue(消息隊列)
?
?
?
1 使用場景
1) 簡單隊列:發布微博,用lpush加入時間軸,最新消息排行,展示新的列表信息
?
2) 消息隊列:PUSH 操作將任務存放在List中,然后工作線程再用 POP操作將任務取出進行執行
?
?
?
2 編碼
1) linkedlist:雙向鏈表,當列表元素個數比較多或者某個元素占用空間比較大的時使用,redis3 .2版本之前使用
?
2) ziplist:壓縮列表,當列表元素個數比較少并且每個元素占用空間比較小時使用,redis3 .2版本之前使用
?
3) quicklist:快速列表,結合了ziplist和linkedlist各自的優點,redis3 .2版本開始使用
?
?
?
三) Set(無序集合)
redis中的Set類型是無序集合,集合中成員是不可重復的
?
添加,刪除,查找元素的復雜度都是 O(1)
?
?
?
1 使用場景
1) 標簽:有同一標簽或者類似標簽的可以給推薦關注的事或者關注的人
?
2) 點贊,點踩,收藏
?
?
?
2 編碼
1) hashtable:數據全部存儲于dict的鍵中,值字段閑置不用
?
2) intset:集合中存儲的只能是數值數據,且必須是整數
?
?
?
3 編碼轉換
同時滿足以下兩個條件時,使用intset編碼,否則使用hashtable編碼
?
1) Set中所有元素都是整數
?
2) Set中所有元素數量不超過512M(配置文件的set-max-intset-entries參數)
?
?
?
四) ZSet(有序集合)
Zset類型和Set類型基本一樣,區別在于Zset類型是有序集合
?
Zset集合中的每個元素都會關聯一個 double 類型的權重參數(score),使得集合中的元素能夠按score進行有序排列
?
添加,刪除,查找元素的復雜度都是 O(1)
?
?
?
1 使用場景
1) 排行榜:如網站需要對用戶點贊數從高到低進行排行
2) 權重分配:帶權重的隊列,如普通消息的score為1,重要消息的score為2,工作線程根據權重倒序獲取,保證重要的任務優先執行
?
?
2 編碼
1) ziplist:需要基于ziplist數據結構的基礎做排序與去重
?
2) skiplist:底層使用了dict與skiplist兩種數據結構
單獨使用dict,雖然能以 O(1) 的時間復雜度查找成員,但dict是無序的,所以進行范圍操作的時候都要進行排序;
?
單獨使用skiplist,雖然能執行范圍操作,但是查找操作為O(logN)
?
因此redis使用了dict與skiplist兩種數據結構來共同實現Zset,既可以以O(1) 的時間復雜度查找成員,又可以實現范圍操作
?
?
?
3 編碼轉換
當Zset對象同時滿足以下兩個條件時,使用 ziplist 編碼,否者使用 skiplist 編碼
?
1) 保存的元素數量小于128(配置文件的zset-max-ziplist-entries參數)
?
2) 保存的所有元素長度都小于64Byte(配置文件的zset-max-ziplist-value參數)
?
?
五) Hash
Hash是一個key(字段) 和 value(屬性) 的映射表,hash 特別適合用于存儲對象
?
一個Hash可以存多個key-value
?
?
?
1 使用場景
1) 緩存:用戶信息,視頻信息等
?
2) 用戶信息
?
3) 用戶主頁訪問量
?
4) 組合查詢
?
?
?
2 編碼
1) ziplist
?
2) hashtable
?
?
?
3 編碼轉換
當同時滿足下面兩個條件時,使用ziplist編碼,否則使用hashtable 編碼
?
1) 列表保存元素個數小于512(配置文件的set-max-intset-entries參數)
?
2) 每個元素長度小于64Byte