Redis筆記(三)- 基礎數據結構_Hash和Set

Redis的hash結構跟Java的HashMap十分相似,同樣都是用數組加鏈表組成(還是是數組和鏈表,和上一節的quicklist組成是一樣的吧,只不過quicklist的結構是由數組組成的鏈表,而hash則是由鏈表組成的數組)。Set內部結構也是hash,只不過hashEntry中所有的 value 都是一個值NULL(又抄我java)。hash表就不多說了,直接上圖,哦,這里要注意,hash結構的值只能是string類型(redis中整數什么的都可以視為string)。


hash.png

探索hash字典內部原理

struct hashEntry {
    void* key;
    void* val;
    hashEntry* next; // 下一個 entry的地址值
}
struct hashTable{
    hashEntry** table; // 二維數組,相當于java中的 new Entry[][]
    long size; // 第一維數組的長度,hash表中數組部分的長度
    long used; // hash 表中的所有元素個數
    ...
}

這個二維數組的行代表著hash表中數組的部分的長度,列代表著hash表中的每一個鏈表的長度。

兩個hashTable

實際上,每個hash類型的數據結構里面都會有兩個hashTable,就是因為在擴容的時候采取了一種漸進式的擴容方式,這種方式會提前創建一個新的hashtable,容量為當前used*2,觸發擴容條件時,將老hashTable的數據分批次遷移到新的hashtable當中,這種方式最大的好處就是不會因為一次性遷移的數據量太大而導致讀寫的阻塞。(CopyOnWriteArrayList是嘛)

在讀請求進來時,如果發現擴容還未結束,會先從老hashTable查,查不到會再從新的hashTable查。而有寫請求時,會順便將這個元素rehash一次,把值直接存到新hashTable中。

擴容時機

1.當hash中元素總個數=hash中數組的長度時,且沒有正在進行bgsave或bgrewriteaof操作(持久化內存快照)。
2.當hash中元素總個數=hash中數組的長度的5倍時,即使正在進行bgsave或bgrewriteaof操作,也會強制擴容。(我覺得紅黑樹還能再挺一下)

縮容時機

當hash中元素總個數=hash中數組的長度的1/10時,便會縮容。

Set中的intset
struct intset {
    uint32_t encoding;//編碼方式,可選16/32/64位
    uint32_t length;//數組長度
    int8_t contents[];//元素
}
intset.png

當set內元素個數較少且都為整型時,set內部結構會優化為一個intset,結構和壓縮列表類似,不過intset的元素都為整型,在intset中定位一個元素時,會使用二分法查找,時間復雜度為O(logn)。
intset 只能升級,不能降級。將一個大于當前encoding位數的元素插入到intset ,會導致intset升級,或者直接變成hash結構。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1 前言 Redis的5種數據類型(String,Hash,List,Set,Sorted Set),每種數據類型...
    LZhan閱讀 389評論 0 2
  • 一、String 1.1.數據結構 注:數組大小=len+free+1(字符的‘\0’休止符) 1.2.空間分配策...
    愛情小傻蛋閱讀 1,768評論 2 0
  • 1.演示數據類型的實現 上篇博客我們在介紹 key 相關命令的時候,介紹了如下命令: ``` OBJECT ENC...
    mkdlp閱讀 406評論 0 0
  • 上一篇文章詳細介紹了Redis的五種常用數據類型,每種數據類型在內存中的數據結構都會因情況而異。接下來,我會用幾篇...
    Javar閱讀 1,942評論 0 2
  • 目錄 1、演示數據類型的實現 2、簡單動態字符串 3、鏈表 4、字典 5、跳躍表 6、整數集合 7、壓縮列表 8、...
    匆匆歲月閱讀 1,185評論 0 28