Redis 字典的實現 2

2021-07-03 12:32:10 字數 1269 閱讀 2144

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 會有部分資料...