《Redis設計與實現》筆記
本書介紹了以下內容:
字串(string)、雜湊(hash)、列表(list)、集合(set)和有序集合(sorted set)這五種型別的鍵的底層實現資料結構。
Redis 的物件處理機制以及資料庫的實現原理。
事務實現原理。
訂閱與釋出實現原理。
Lua 指令碼功能的實現原理。
SORT 命令的實現原理。
BITOP 、 BITCOUNT 等二進位制位處理命令的實現原理。
慢查詢日誌的實現原理。
RDB 持久化和 AOF 持久化的實現原理。
Redis 事件處理器的實現原理。
Redis 伺服器和客戶端的實現原理。
複製(replication)、Sentinel 和叢集(cluster)這三個多機功能的實現原理。
簡單動態字串
字串(String)使用了一種稱為簡單動態字串(Simple Dynamic String)的抽象資料型別,以空字元結尾,len + free + 1 = buf.length。
'''
struct sdshdr {
// buf 中已佔用空間的長度
int len;
// buf 中剩餘可用空間的長度
int free;
// 資料空間
char buf[];
};
'''
與C語言字串的區別:
- O(1) 時間複雜度獲取字串長度
- 避免緩衝區溢位:拼接前進行長度檢查
- 減少記憶體分配次數
- 空間預分配:newlen = (len+addlen); newlen = newlen + min(newlen, SDS_MAX_PREALLOC);
- 惰性空間釋放
- 二進位制安全:C語言字串中不能包含空字串(因此不能儲存像圖片、音訊、視訊、壓縮檔案這樣的二進位制資料),否則被判為結尾,而SDS用len判定
- 相容部分C語言字串函式
連結串列
列表鍵的底層實現結構之一是雙向連結串列(也可能是壓縮列表)。當列表鍵包含了許多元素,或者元素是比較長的字串的時候,就會用到連結串列作為列表鍵的底層實現。
字典
字典,鍵值對,Redis資料庫的儲存就是用的hash索引,也是hash鍵的底層實現之一。
字典有2個雜湊表,雜湊表有一個dictEntry陣列,dictEntry 雜湊節點包含鍵、值、next。
- 雜湊演算法:index = hashFunc(key) & sizemask,採用高速的murmurhash2演算法
- 鍵衝突解決:採用鏈地址法,插到頭部(O(1))
- rehash:
- 裝載因子=鍵值對/雜湊表大小,0.1、1、5時
- 申請空間:擴容——2*x的最小2的n次方;收縮——x的最小2的n次方
- 漸進式rehash到 ht[1]上,對字典進行增刪改查的時候進行一步rehash、將ht[0] rehashidx位置的資料遷移到ht[1]上,直到完成
跳錶
平均O(logN),最壞O(N),支援順序遍歷查詢。有序集合元素較多或是元素成員是比較長的字串時就會使用跳錶。
分值可以相同,成員物件必須唯一,跨度用來計算排位。
整數集合(intset)
保持升序、不重複的一個整數陣列。當一個集合只包含整數值元素,並且這個集合的元素數量不多時,Redis就會使用整數集合作為集合鍵的底層實現。
升級:int32—>int64,重新分配陣列空間。不支援降級。
壓縮列表(ziplist)
list(元素少,小整數或短字串時) 和 hash 的底層實現之一。
連鎖更新:插入、刪除最壞情況下N次空間重分配,每次最壞O(N),總共O(N^2)。但這個條件較苛刻,平均O(N)。
物件
字串(string)、雜湊(hash)、列表(list)、集合(set)和有序集合(sorted set),Redis使用物件來表示資料庫中的鍵和值,實現了基於引用計數的記憶體回收機制。
物件的型別(5種)和編碼(底層實現)。