Redis 的數據架構,能夠參考下圖:web
Redis中的全部 value 都是以 Object 的形式存在的,其通用結構以下: redis
typedef struct redisObject {
unsigned [type] 4;
unsigned [encoding] 4;
unsigned [lru] REDIS_LRU_BITS;
int refcount;
void *ptr;
} robj;
複製代碼
Redis 中的 String 不單單表示 字符串,還能夠表示 整型、浮點型。緩存
String 的編碼能夠是 int、raw 或者 embstr;單說普通的字符串,就有 raw 和 embstr 兩種實現方式,embstr 是 Redis 3.0 新增的數據結構:數據結構
字符串長度小於 39 字節,就用 embstr 對象,不然用傳統的raw對象(Redis 3.2 版本以後,這裏變成了以 44 字節爲分界)。架構
embstr 的優點在於建立時少分配一次空間(RedisObject 和 sds 是連續的),刪除時少釋放一次空間,以及對象的全部數據連在一塊兒,尋找方便;app
固然缺點也很是明顯,若是字符串的長度增長,須要從新分配內存的時候,整個 RedisObject 和 sds 都須要從新分配空間。網站
修改 embstr 對象的時候,Redis 會將其轉換成 raw 格式再進行修改,因此 embstr 對象修改以後的對象,必定是 raw 的。編碼
應用場景:常規計數均可以使用,可用做緩存、計數、限速等等,好比商品剩餘數量,字典表信息,長度不能超過 512MB。spa
Hash 對象的底層實現能夠是 ziplist 或者 hashtable。code
ziplist:在這個數據結構中,是按照 key1, value1, key2, value2 這樣的順序存放來存儲的;
hashTable:是由 dict 這個結構來實現的。(這個結構比較複雜,後面單寫一篇來講)
應用場景:Hash 適用於存儲結構化的對象,能夠直接修改這個對象中的某個字段的值;好比用戶信息。
List 對象的編碼能夠是 ziplist 或者 linkedlist,從名字上也能看出來兩種結構都是啥。
ziplist:是一種壓縮鏈表,它存儲數據都是連續地放在內存區域當中。
linkedlist:是一種雙向鏈表。
應用場景:一般網站上的消息列表,可使用 List 來進行存儲;另外 lrange 命令,從某個元素開始,讀取多少個元素,能夠看作是分頁查詢,好比不少網站上那種不斷下拉,不斷分頁的效果。
Set 相對於 List 來講,Set 是能夠自動排重的;它的編碼能夠是 **intset 或者 hashtable **。
intset:是一個整數集合,支持三種長度的整數:int16_t、int32_t、int64_t;集合中的數據長度必須是一致的,好比一個 int16_t 長度的 Set,當插入了一條 int32_t 長度的數據,那麼全部的數據都會轉成 int32_t 長度(不支持降級)。
hashTable:對於 Set 來講,hashTable 的 value 永遠爲 NULL。
應用場景:若是要存儲一個列表,同時又須要作數據排重的時候,可使用 set ;另外,Redis 還爲 Set 提供了求交集、並集、差集等操做,好比微博上面的【共同關注】這個功能,就能夠用 Set 實現。
和 Set 相比,ZSet 增長了一個參數 score,集合中的元素按照 score 進行有序排列。
有序集合的編碼可能兩種,一種是 ziplist,另外一種是 skipList 與 hashTable 的結合。
ziplist:和 Hash 相似,元素 和 score 都是按順序存放的;比較適合用於元素內容不大的場景。
skipList + hashTable:是一種添加,移除,更新元素等操做更高效的數據結構,這個跳躍表的數據結構,我近期會發一篇文章單獨介紹。
應用場景:有序 + 排重的場景,好比常常玩遊戲的同窗,應該不會陌生各類排行榜,就可使用 ZSet 來實現。
會點代碼的大叔 | 文【原創】