標籤:
文中內容摘自《redis設計與實現》
簡單動態字串
1. redis自己構建了一種名為簡單動態字串(simple dynamic string,SDS)的抽象類別型,並將SDS用作Redis的預設字串表示
2. SDS屬性:
1). free : 未使用的空間
2). len : 已儲存字串的長度
3). buf : char類型數組,字串儲存的內容,最後一個位元組是一個Null 字元‘\0‘
3. SDS遵循C字串以Null 字元串結尾的慣例,儲存Null 字元的1位元組空間不計算在SDS的len屬性裡面。遵循Null 字元串慣例的好處是,SDS可以直接重用一部分C字串函數庫裡的函數。
4. SDS與C字串的區別:
1). C字串擷取字串的長度的複雜度為O(N),SDS擷取字串長度的複雜度為O(1)
2). C字串的API是不安全的,可能會造成緩衝區溢位。SDS的API是安全的,不會造成緩衝區地溢出。
3). C字串修改字串的長度N次必然需要執行N此記憶體配置。SDS修改字串長度N次最多需要執行N此記憶體重新分配。SDS減少修改字串時帶來的記憶體重新分配次數的方式:
a. 空間預分配
b. 惰性空間釋放
4). C字串只能儲存文本資料。SDS可以儲存或者位元據。
5). SDS只能相容部分C字串函數
5. 二進位安全:隨熱按資料庫一般用於儲存文本資料,但使用資料庫來儲存位元據的情境也不少見。為了確保Redis可以適用於各種不同的使用情境,SDS的API都是二進位安全的,
所有SDS API都會以二進位的方式來處理SDS存放在buf數組裡的資料。程式不會對其中的資料做任何的限制、過濾、或者假設,資料寫入時什麼樣的,他被讀取就是什麼樣的。
鏈表:
Redis的鏈表實現的特徵可以總結如下:
1. 雙端:鏈表節點帶有prev和next指標,擷取某個節點的前置節點和後置節點的複雜度都是O(1)
2. 無環:表前端節點的prev指標和表尾節點的next指標都指向NULL,對鏈表的訪問以NULL為節點。
3. 帶表頭指標和表尾指標:通過list結構的head指標和tail指標,程式擷取鏈表的表前端節點和表尾節點的複雜度為O(1)
4. 帶鏈表長度計數器:程式使用list結構的len屬性來對list持有的鏈表節點進行計數,程式擷取鏈表中節點數量複雜度為O(1)
5. 多態:鏈表節點使用void*指標來儲存節點值,並且可以通過list結構的dup、free、match三個屬性為節點值設定類型特定函數,所以鏈表可以用於儲存各種不同類型的值。
6. 鏈表被廣泛用於redis的各種功能,比如列表鍵、發布與訂閱、慢查詢、監視器等
字典:
1. 字典,又稱為符號表,關聯陣列或映射,是一種用於儲存索引值對的抽象資料結構。
2. Redis的字典使用雜湊表作為底層實現,一個雜湊表裡面可以有多個雜湊表節點,而每個雜湊表節點就儲存了字典中的一個索引值對。
3. 字典被廣泛用於實現Redis的各種功能,其中包括資料庫和雜湊鍵。
4. Redis中的字典使用暗黑系表作為底層實現,每個字典帶有兩個雜湊表,一個平時使用,另一個僅在進行rehash時使用。
5. 雜湊表使用鏈地址法來解決鍵衝突,被分配到同一個索引上的多個索引值對會串連成單向鏈表。最新的索引值在最上面,便於訪問。
6. 在對雜湊表進行擴充或者收縮操作時,程式需要將現有的雜湊表包含的所有索引值對rehash到新雜湊表裡面,並且這個rehash過程並不是一次性完成的,而是漸進式的。
7. 因為在進行漸進式rehash的過程中,字典會同時使用ht[0]和ht[1]兩個雜湊表,所有在漸進式rehash進行期間,字典的刪除、尋找、更新等操作會在兩個雜湊表上進行。先找ht[0],再找ht[1].
另外,在漸進式rehash期間,新添加到字典中的索引值對一律被儲存到ht[1]中。
8. 雜湊表的擴充與收縮:
滿足一下任意條件時,執行擴充操作:
1). 伺服器目前沒有在執行BGSAVE或者BGREWRITEAOF命令,並且雜湊表的負載因子大於等於1。
2). 伺服器目前正在執行BGSAVE或者BGREWRITEAOF命令,並且雜湊表的負載因子大於等於5
另一方面,當雜湊表的負載因子小於0.1時,程式自動開始對雜湊表執行收縮操作。
跳躍表:
1. 跳躍表是以各種有序資料結構,它通過在每個節點中維持多個指向其他節點的指標,從而達到快速存取節點的目的。
2. Redis只有兩個地方用到跳躍表:一個是實現有序集合鍵,另一個是在叢集節點中用作內部資料結構。
3. 跳躍表是有序集合的底層實現之一。
4. Redis的跳躍表實現由zskiplist和zskiplistNode兩個結構組成,其中zskiplist用於儲存跳躍表資訊(比如表前端節點、表尾節點、長度),而zskiplistNode則用於表示跳躍表節點。
5. 每個跳躍表節點的層高都是1至32之間的隨機數。
6. 在同一個跳躍表中,多個節點可以包含相同的分值,但每個節點的成員對象必須是唯一的。
7. 跳躍表的節點按照分值大小進行排序,當分值相同時,節點按照成員對象的大小進行排序。
redis 筆記01