Redis 儲存結構設計

來源:互聯網
上載者:User
Redis是一個包含了很多Key-Value對的大字典,這個字典支援的Value非常豐富,可以為字串、雜湊表、列表、集合和有序集,基於這些類型豐富的value,擴充出了功能強大的操作,例如hmset、lpush、sadd等


1、字典
字典是Redis最基礎的資料結構,一個字典即一個DB,Redis支援多DB
Redis字典採用Hash表實現,針對碰撞問題,其採用的方法為“鏈地址法”,即將多個雜湊值相同的節點串聯在一起, 從而解決衝突問題。
“鏈地址法”的問題在於當碰撞劇烈時,效能退化嚴重,例如:當有n個資料,m個槽位,如果m=1,則整個Hash表退化為鏈表,查詢複雜度O(n)
為了避免Hash碰撞攻擊,Redis隨機化了Hash表種子

Redis的方案是“雙buffer”,正常流程使用一個buffer,當發現碰撞劇烈(判斷依據為當前槽位元和Key數的對比),分配一個更大的buffer,然後逐步將資料從老的buffer遷移到新的buffer。


2、Redis中的雜湊表

前面提到Redis是個key/value儲存系統,學過資料結構的人都知道,key/value最簡單的資料結果就是雜湊表(當然,還有其他方式,如B-樹,二叉平衡樹等),hash表的效能取決於兩個因素:hash表的大小和解決衝突的方法。這兩個是矛盾的:hash表大,則衝突少,但是用記憶體過大;而hash表小,則記憶體使用量少,但衝突多,效能低。一個好的hash表會權衡這兩個因素,使記憶體使用量量和效能均儘可能低。在Redis中,雜湊表是所有其他資料結構的基礎,對於其他所有資料結構,如:string,set,sortedset,均是儲存到hash表中的value中的,這個可以很容易的通過設定value的類型為void*做到。本文詳細介紹了Redis中hash表的設計思想和實現方法。

3、Redis雜湊表的設計思想

下圖是從淘寶《Redis記憶體儲存結構分析》中摘得的圖片,主要描述Redis中hash表的組織方式。


在Redis中,hash表被稱為字典(dictionary),採用了典型的鏈式解決衝突方法,即:當有多個key/value的key的映射值(每對key/value儲存之前,會先通過類似HASH(key) MOD N的方法計算一個值,以便確定其對應的hash table的位置)相同時,會將這些value以單鏈表的形式儲存;同時為了控制雜湊表所佔記憶體大小,redis採用了雙雜湊表(ht[2])結構,並逐步擴大雜湊表容量(桶的大小)的策略,即:剛開始,雜湊表ht[0]的桶大小為4,雜湊表ht[1]的桶大小為0,待衝突嚴重(redis有一定的判斷條件)後,ht[1]中桶的大小增為ht[0]的兩倍,並逐步(注意這個詞:”逐步”)將雜湊表ht[0]中元素遷移(稱為“再次Hash”)到ht[1],待ht[0]中所有元素全部遷移到ht[1]後,再將ht[1]交給ht[0](這裡僅僅是C語言地址交換),之後重複上面的過程。


Redis字典結構如下:
[cpp]  view plain copy typedef struct dict {       dictType *type;        void *privdata;        dictht ht[2]; //雙buffer       int rehashidx;        int iterators;   } dict;      typedef struct dictht {       dictEntry **table; //hash鏈表       unsigned long size;       unsigned long sizemask;       unsigned long used;   } dictht;      //資料節點<K,V>   typedef struct dictEntry {       void *key;       union {           void *val;           uint64_t u64;           int64_t s64;       } v;       struct dictEntry *next;   } dictEntry;   redisObject是真正儲存redis各種類型的結構,其內容如下:
[cpp]  view plain copy typedef struct redisObject {       unsigned type:4; //邏輯類型       unsigned notused:2;     /* Not used */       unsigned encoding:4; //實體儲存體類型       unsigned lru:22;        /* lru time (relative to server.lruclock) */       int refcount;       void *ptr;  //具體資料   } robj;   其中type即redis支援的邏輯類型,包括:
[cpp]  view plain copy #define REDIS_STRING 0   #define REDIS_LIST 1   #define REDIS_SET 2   #define REDIS_ZSET 3   #define REDIS_HASH 4   enconding為實體儲存體方式,一種邏輯類型可以使用不同的儲存方式,包括:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.