1.redis 字典 hash演算法
根據key計算hash值
hash = dict -> type -> hashfunction(key);
根據sizemask屬性和雜湊值,計算出索引,ht[x]可以是ht[0]或ht[1]
index = hash & dict -> ht[x].sizemask;
redis使用murmurhash2演算法計算鍵的雜湊值,優點在於即使輸入的鍵是有規律的,演算法仍能給出乙個很好的隨機分布性。
2.解決hash衝突
當2個或多個不同物件的hash值相同時,會被分配到雜湊表的同乙個索引上,此時就稱之為雜湊衝突。
redis採用鏈位址法解決鍵衝突,每個雜湊節點都有乙個next指標,由此指標構成乙個單向鍊錶,新新增的元素在煉表表頭。
3.rehash
負載因子 = 雜湊表節點數量/雜湊表大小
load_factor = ht[0].used / ht[0].size
當雜湊表的操作不斷進行,需要把雜湊表的負載因子保持在乙個合理範圍內,需要對雜湊表進行擴容或縮容操作,2種操作都通過執行再雜湊操作來執行(rehash):
a.為字典的ht[1]分配空間,如果是擴容操作,ht[1]的空間為ht[0]的節點數量2倍;如果是縮容,ht[1]的空間為ht[0]節點數量的一半。
b.將ht[0]中的所有鍵值對rehash到ht[1]上面:rehash需要重新計算鍵的雜湊值和索引值,然後放在ht[1]的指定位置上。
c.當ht[0]所有鍵值對都遷移到ht[1]上之後,釋放ht[0],就是將ht[0]表置為空表,再將ht[1]置為ht[0],並將ht[1]新建乙個大小為0的空雜湊表。
4.漸進式rehash
上面講到rehash過程中,需要將ht[0]上的鍵值對遷移到ht[1]上,但這個過程並不是一次性操作完成的。如果需要一次性完成,就必須對當前雜湊表進行鎖表操作,鎖表期間會導致服務的不可用,所以rehash操作需要分多次、漸進式的完成。
a.為ht[1]分配空間,字典同時持有ht[0]和ht[1]兩個雜湊表
b.將rehashidx值置為0,表示rehash工作開始。
c.rehash期間,所有對字典執行的讀寫操作,都會在ht[0]和ht[1]兩個表上操作,讀操作如果在ht[0]上找到,會把結果rehash到ht[1]上,如果未找到會到ht[1]上去找,儲存操作只會存在ht[1]上,當rehash工作完成之後,rehashidx++;
d.隨著字典操作的不斷執行,最終ht[0]上所有節點會全部rehash到ht[1]上,這時將rehashidx值置為-1,表示rehash完成。
Redis的設計與實現 字典
參考部落格 絕大多數語言中的字典底層實現基本上都是雜湊表。雜湊表中用 負載因子 來衡量雜湊表的空 滿程度。為了讓負載因子在一定的合理範圍之內,提高查詢的效能,一般的做法是讓雜湊表擴容,然後rehash一把。but,擴容也不一定就能解決負載因子過大的問題。redis作為一款成熟的非關係型資料庫,肯定有...
Redis設計於實現之字典
簡介 字典實現 字典的實現是以雜湊表作為它的底層實現,乙個雜湊表可以有多個雜湊表節點,每個節點儲存了字典中的乙個鍵值對。1.雜湊表節點 key就是鍵,v就是鍵中的值 可以是指標,unit64 t 整數,int64 t s64整數 next是將另外乙個雜湊值相同的鍵值對連線在一起的指標 為了解決衝突 ...
Redis 初探dict字典原理的實現 二
時間頗為倉促,以下簡單概括一下dict的基礎與核心的知識點 1.應用範圍 redis中字典的應用範圍非常廣泛 資料庫的鍵空間,hash型別等都是通過字典來實現的.2.rehash 內部維持了兩個hashtable,ht 0 為當前所用到的儲存ht 如果正在rehasing,那麼ht 0 會有部分資料...