Redis設計與實現
第一部分 資料結構與物件
第二章 簡單動態字串
- p8 簡單動態字串SDS
2.1 SDS的定義
- p9 每個sds.h/sdshdr結構表示一個SDS值
2.2 SDS與C字串的區別
- p10 常數複雜度獲取字串長度
- p10 獲取一個SDS長度的複雜度僅為O(1)
- p11 杜絕緩衝區溢位
- p11 SDS修改操作
- p12 減少修改字串帶來的記憶體重分配次數
- p13 空間預分配
- p14 惰性空間釋放
- p15 二進位制安全
- p16 SDS的二進位制安全
- p16 相容部分C字串函式
- p17 SDS可以在有需要時重用<String.h>函式庫
- p17 總結
- p17 C字串和SDS之間的區別
2.3 SDS API
- P17 SDS的主要操作API
2.4 重點回顧
- p18 SDS相比C字串的優點
第三章 連結串列
3.1 連結串列和連結串列節點的實現
- p20 list結構
- p21 Redis連結串列的實現特性
3.2 連結串列和連結串列節點的API
- p21 用於操作連結串列和連結串列節點的API
3.3 重點回顧
第四章 字典
4.1 字典的實現
-
p24 雜湊表
- p24 dictht結構
-
p25 雜湊表節點
- p25 dictEntry結構
-
p26 字典
- p26 dic結構
4.2 雜湊演算法
- p27 Redis計算雜湊值和索引值的方法
- p28 Redis使用MurmurHash2演算法計算鍵的雜湊值
4.3 解決鍵衝突
- p28 Redis的雜湊表使用鏈地址法解決鍵衝突
4.4 rehash
- p29 Redis對字典的雜湊表執行rehash的步驟如下
- p32 雜湊表的擴充套件與收縮
- p32 負載因子
4.5 漸進式rehash
- p33 漸進式rehash詳細步驟
- p36 漸進式rehash執行期間的雜湊表操作
4.6 字典API
- p36 字典的主要操作API
第五章 跳躍表
- p38 跳躍表
5.1 跳躍表的實現
-
p39 跳躍表由zskiplistNode和zskiplist兩個結構定義
-
p39 zskiplist結構
-
p40 跳躍表節點
- p40 zskiplistNode結構
- p40 層
- p40 前進指標
- p41 跨度
- p42 後退指標
- p42 分值和成員
- p43 跳躍表
- p40 zskiplistNode結構
5.2 跳躍表API
- p44 跳躍表的所有操作API
第六章 整數集合
6.1 整數集合的實現
- p47 contents陣列(整數集合底層實現)的真正型別取決於encoding的值
6.2 升級
- p48 升級整數集合並新增新元素的三步驟
- p50 升級之後新元素的擺放位置
6.3 升級的好處
- p50 提升靈活性
- p50 節約記憶體
6.4 降級
6.5 整數集合API
- p51 整數集合的操作API
第七章 壓縮連結串列
- p52 壓縮連結串列概念
7.1 壓縮連結串列的構成
- p53 壓縮連結串列組成部分詳細說明
7.2 壓縮連結串列節點的構成
- p54 previous_entry_length
- p55 壓縮連結串列從表尾節點向表頭結點進行遍歷的完整過程
- p55 encoding
- p56 content
7.3 連鎖更新
- p58 連鎖更新
7.4 壓縮連結串列API
- p59 壓縮連結串列API
第八章 物件
8.1 物件的型別與編碼
- p61 redisObject結構
- p61 型別
- p61 物件的型別
- p61 TYPE命令
- p62 編碼和底層實現
- p62 encoding屬性記錄了物件所使用的編碼
- p62 每種型別的物件可以使用的編碼
- p63 OBJECT ENCODING命令
8.2 字串物件
- p64 字串物件的編碼可以是int、raw或者embstr
- p65 embstr編碼的字串物件來儲存短字串值的好處
- p66 字串物件儲存各型別值得編碼方式
- p66 編碼的轉換
- p67 字串命令的實現
8.3 列表物件
- p68 列表物件的編碼可以是ziplist或者Linkedlist
- p70 編碼轉換
- p70 列表物件使用ziplist編碼的兩個條件
8.4 雜湊物件
- p71 雜湊物件的編碼可以是ziplist或者hashtable
- p73 編碼轉換
- p73 雜湊物件使用ziplist編碼的兩個條件
- p74 雜湊命令的實現
8.5 集合物件
- p75 集合物件的編碼可以是intset或者hashtable
- p75 編碼的轉換
- p75 集合物件使用intset編碼的兩個條件
- p76 集合命令的實現
8.6 有序集合物件
- p77 有序集合物件的編碼可以是ziplist或者skiplist
- p78 為什麼有序集合需要同時使用跳躍表和字典來實現
- p79 編碼的轉換
- p79 有序集合物件使用ziplist編碼的兩個條件
- p80 有序集合命令的實現
8.7 型別檢查與命令多型
- p82 型別檢查的實現
- p83 型別檢查過程
- p83 多型命令的實現
- p83 一些命令是多型的
8.8 記憶體回收
- p84 Redis使用引用計數法實現記憶體回收機制
- p84 引用計數規則
8.9 物件共享
- p85 讓多個鍵共享同一個值物件需要執行兩個步驟
- p86 Redis在初始化伺服器時建立了一萬個字串物件,包含0到9999的所有整數值,並將它們作為共享物件
- p86 OBJECT REFCOUNT命令
- p87 為什麼Redis不共享包含字串的物件
8.10 物件的空轉時長
- p87 OBJECT IDLETIME命令
第二部分 單機資料庫的實現
第九章 資料庫
9.1 伺服器中的資料庫
- p90 redisServer結構和redisDb結構
9.2 切換資料庫
- p91 SELECT命令
- p92 SELECT命令實現原理
9.3 資料庫鍵空間
- p93 鍵空間
- p94 新增新鍵
- p95 刪除鍵
- p95 更新鍵
- p97 對鍵取值
- p98 其他鍵空間操作
- p98 讀寫鍵空間時的維護操作
- p98 伺服器會記錄鍵空間命中次數或鍵空間不命中次數
- p98 鍵的LRU時間
- p99 髒鍵標記
9.4 設定鍵的生存時間或過期時間
- p99 EXPIRE命令和PEXPIRE命令
- p99 EXPIREAT命令和PEXPIREAT命令
- p100 TTL命令和PTTL命令
- p100 設定過期時間
- p101 設定生存時間和設定過期時間的命令之間的轉換
- p101 儲存過期時間
- p101 過期字典
- p104 移除過期時間
- p104 PERSIST命令
- p105 計算並返回剩餘生存時間
- p105 TTL命令和PTTL命令
- p106 過期鍵的判定
9.5 過期鍵刪除策略
- p107 定時刪除
- p108 惰性刪除
- p108 定期刪除
9.6 Redis的過期鍵刪除策略
- p108 Redis伺服器實際使用的是惰性刪除和定期刪除兩種策略
- p109 惰性刪除策略的實現
- p109 定期刪除策略的實現
9.7 AOF、RDB和複製功能對過期鍵的處理
-
p111 生成RDB檔案
- p111 已過期的鍵不會被儲存到新建立的RDB檔案中
-
p111 載入RDB檔案
-
p112 AOF檔案寫入
-
p112 AOF重寫
-
p112 複製
-
p113 資料庫通知
9.8 資料庫通知
- p113 資料庫通知
- p114 鍵空間通知和鍵事件通知
- p114 notify-keyspace-events選項決定了伺服器所傳送通知的型別
- p115 傳送通知
- p115 notifyKeyspaceEvent函式實現了傳送資料庫通知的功能
- p116 傳送通知的實現
第十章 RDB持久化
- p118 資料庫狀態
10.1 RDB檔案的建立與載入
- p119 SAVE命令和BGSAVE命令
- p120 AOF檔案的更新頻率通常比RDB檔案的更新頻率高
- p120 SAVE命令執行時的伺服器狀態
- p120 SAVE命令執行時,Redis伺服器將被阻塞
- p120 BGSAVE命令執行時候的伺服器狀態
- p121 BGSAVE命令執行期間,伺服器處理SAVE、BGSAVE、BGREWRITEAOF三個命令的方式會發生變化
- p121 RDB檔案載入時的伺服器狀態
- p121伺服器在載入RDB檔案期間,會一直處於阻塞狀態,直到載入工作完成
10.2 自動間隔性儲存
- p121 save選項
- p122 設定儲存條件
- p122 save選項預設條件
- p123 dirty計數器和lastsave屬性
- p124 設定儲存條件是否滿足
- p124 伺服器週期性操作函式serverCron
10.3 RDB檔案結構
-
p125 RDB檔案結構
-
p126 check_sum校驗和
-
p126 databases部分
- p126 RDB檔案中的資料庫結構
-
p127 key_value_pairs部分
- p127 不帶過期時間的鍵值對結構
- p128 帶有過期時間的鍵值對結構
-
p128 value的編碼
10.4 分析RDB檔案
- p133 od命令可以分析RDB檔案
- p133 不包含任何鍵值對的RDB檔案
- p134 包含字串鍵的RDB檔案
- p135 包含帶有過期時間的字串鍵的RDB檔案
- p135 包含一個集合鍵的RDB檔案
- p136 關於分析RDB檔案的說明
第十一章 AOF持久化
11.1 AOF持久化的實現
- p139 命令追加
- p140 AOF檔案的寫入與同步
- p140 Redis的伺服器程式是一個事件迴圈
- p140 appendfsync選項
- p141 檔案的寫入和同步
11.2 AOF的載入與資料還原
- p142 Redis讀取AOF檔案並還原資料庫的詳細步驟
11.3 AOF重寫
- p143 AOF重寫
- p143 AOF檔案重寫的實現
- p144 AOF重寫功能的實現原理
- p147 元素數量超過一個引數時,重寫程式使用多條命令來記錄鍵的值
- p147 AOF後臺重寫
- p148 AOF重寫緩衝區
第十二章 事件
- p151 檔案事件和時間事件
12.1 檔案事件
- p151 檔案事件處理器
- p152 檔案事件處理器的構成
- p152 I/O多路複用程式的實現
- p152 Redis的I/O多路複用程式的所有功能都是通過包裝常見的I/O多路複用函式庫來實現的
- p153 事件的型別
- p153 READABLE事件和WRITABLE事件
- p153 API
- p154 檔案時間的處理器
- p154 連線應答處理器
- p155 命令請求處理器
- p155 命令回覆處理器
- p155 一次完整的客戶端與伺服器連線事件示例
12.2 時間事件
- p156 定時事件和週期性事件
- p157 時間事件的實現
- p157 API
- p159 時間事件應用例項:serverCron函式
12.3 事件的排程與執行
- p160 事件處理角度下的伺服器執行流程
第十三章 客戶端
- p162 redisClient結構-客戶端狀態
- p163 clients連結串列
13.1 客戶端屬性
- p163 套接字描述符
- p164 名字
- p165 標誌
- p166 PUBSUB命令和SCRIPT LOAD命令的特殊性
- p167 輸入緩衝區
- p168 命令與命令引數
- p169 命令的實現函式
- p169 命令表
- p169 輸出緩衝區
- p171 身份驗證
- p171 時間
- p172 客戶端空轉時間
13.2 客戶端的建立與關閉
- p172 建立普通客戶端
- p173 關閉普通客戶端
- p173 普通客戶端關閉的原因
- p173 兩種限制客戶端輸出緩衝區大小的方式
- p174 Lua指令碼的偽客戶端
- p174 AOF檔案的偽客戶端
第十四章
14.1 命令請求的執行過程
- p177 傳送命令請求
- p177 讀取命令請求
- p178 命令執行器(1):查詢命令實現
- p178 redisCommand結構的主要屬性
- p179 slags屬性的標識
- p181 命令名字的大小寫不影響命令表的查詢結果
- p181 命令執行器(2):執行預備操作
- p182 命令執行器(3):呼叫命令的實現函式
- p183 命令執行器(4):執行後續工作
- p184 將命令回覆傳送給客戶端
- p184 客戶端接收並列印命令回覆
14.2 serverCron函式
- p184 更新伺服器時間快取
- p185 更新LRU時鐘
- p186 更新伺服器每秒執行命令次數
- p187 更新伺服器記憶體峰值記錄
- p188 處理SIGTERM訊號
- p189 管理客戶端資源
- p189 管理資料庫資源
- p189 執行被延遲的BGREWRITEAOF
- p190 檢查持久化操作的執行狀態
- p191 將AOF緩衝區中的內容寫入AOF
- p191 關閉非同步客戶端
- p191 增加cronloops計數器的值
14.3 初始化伺服器
- p192 初始化伺服器狀態結構
- p193 initServerConfig函式
- p193 載入配置選項
- p194 初始化伺服器資料結構
- p194 initServer函式
- p195 共享物件
- p195 還原資料庫狀態
- p196 執行事件迴圈
第三部分 多機資料庫的實現
第十五章 複製
15.1 舊版複製功能的實現
- p199 SYNC命令執行步驟
- p200 命令傳播
15.2 舊版複製功能的缺陷
- p201 初次複製和斷線後重複製
- p203 SYNC命令是一個非常耗費資源的操作
15.3 新版複製功能的實現
- p203 完整重同步和部分重同步
15.4 部分重同步的實現
-
p205 複製偏移量
-
p206 複製積壓緩衝區
- p206 固定長度先進先出佇列
- p209 根據需要調整複製積壓緩衝區大小
-
p208 伺服器執行ID
15.5 PSYNC命令的實現
- p209 PSYNC命令的兩種呼叫方法
- p209 接收到PSYNC命令的主伺服器向從伺服器返回的三種回覆
15.6 複製的實現
- p211 步驟1:設定主伺服器的地址和埠
- p212 步驟2:建立套接字連線
- p212 步驟3:傳送PING命令
- p213 步驟4:身份驗證
- p214 步驟5:傳送埠資訊
- p215 步驟6:同步
- p216 步驟7:命令傳播
15.7 心跳檢測
- p216 傳送REPLCONF ACK命令對於主從伺服器有三個作用
- p216 檢測主從伺服器的網路連線狀態
- p217 輔助實現min-slaves配置選項
- p127 檢測命令丟失
- p218 Redis2.8版本以前的命令丟失
第十六章 Sentinel
- p219 Sentinel
- p220 故障轉移操作
16.1 啟動並初始化Sentinel
- p220 啟動一個Sentinel可以使用命令redis-sentinel
- p221 當一個Sentinel啟動時,它需要以下步驟
- p221 初始化伺服器
- p221 Sentinel模式下Redis伺服器主要功能的使用情況
- p222 使用Sentinel專用程式碼
- p222 初始化Sentinel狀態
- p223 初始化Sentinel狀態的master屬性
- p223 每個sentinelRedisInstence結構代表一個被監視的Redis伺服器例項
- p226 建立連向主伺服器的網路連線
- p226 Sentinel會建立兩個連向主伺服器的非同步網路連線
16.2 獲取主伺服器資訊
- p227 主伺服器INFO命令回覆
16.3 獲取從伺服器資訊
- p229 從伺服器INFO命令回覆
16.4 向主伺服器和從伺服器傳送資訊
- p230 資訊中和Sentinel有關的引數
- p231 資訊中和主伺服器有關的引數
16.5 接收來自主伺服器和從伺服器的頻道資訊
- p232 更新sentinels字典
- p234 建立連向其他Sentinel的命令連線
- p234 Sentinel之間不會建立訂閱連線
16.6 檢測主觀下線狀態
- p235 down-after-milliseconds選項
- p235 主觀下線時長選項的作用範圍
- p236 多個Sentinel設定的主觀下線時長可能不同
16.7 檢查客觀下線狀態
- p236 傳送SENTINEL is-master-down-by-addr命令
- p237 接收SENTINEL is-master-down-by-addr命令
- p237 接收SENTINEL is-master-down-by-addr命令的回覆
- p238 客觀下線狀態的判斷條件
16.8 選舉領頭Sentinel
- 當一個主伺服器被判斷為客觀下線時進行選舉
16.9 故障轉移
- p240 故障轉移的三個步驟
- p241 選出新的主伺服器
- p241 新的主伺服器是怎樣挑選出來的
- p242 修改從伺服器的複製目標
- p243 將舊的主伺服器變為從伺服器
第十七章 叢集
17.1 節點
- p245 CLUSTER MEET命令
- p247 啟動節點
- p247 叢集資料結構
- p247 clusterNode結構
- p248 clusterLink結構
- p249 clusterState結構
- p250 CLUSLTER MEET命令的實現
17.2 槽指派
- p253 記錄節點的槽指派資訊
- p254 傳播節點的槽指派資訊
- p255 記錄叢集所有槽的指派資訊
- p257 CLUSTER ADDSLOTS命令的實現
17.3 在叢集中的執行命令
- p260 計算鍵屬於哪個槽
- p260 判斷槽是否由當前節點負責處理
- p261 MOVED錯誤
- p261 節點資料庫的實現
- p261 slots_to_key跳躍表
17.4 重新分片
- p266 重新分片的實現原理
17.5 ASK錯誤
- p268 CLUSTER SETSLOT IMPORTING命令的實現
- p269 CLUSTER SETSLOT MIGRATING命令的實現
- p270 ASK錯誤
- p271 ASKING命令
- p273 ASK錯誤和MOVED錯誤的區別
17.6 複製與故障轉移
- p275 設定從節點
- p278 故障檢測
- p280 故障轉移
- p280 選舉新的主節點
17.7 訊息
- p282 訊息頭
- p284 MEET、PING、PONG訊息的實現
- p284 Gossip協議
- p285 FAIL訊息的實現
- p286 PUBLISH訊息的實現
第四部分 獨立功能的實現
第十八章 釋出與訂閱
- p290 SUBSCRIBE命令
- p290 PSUBSCRIBE命令
18.1 頻道的訂閱與退訂
- p292 pubsub_channels字典
- p293 訂閱頻道
- p294 退訂頻道
18.2 模式的訂閱與退訂
- p296 訂閱模式
- p297 退訂模式
18.3 傳送訊息
- p298 將訊息傳送給頻道訂閱者
- p299 將訊息傳送給模式訂閱者
18.4 檢視訂閱資訊
- p301 PUBSUB CHANNELS
- p301 PUBSUB NUMSUB
- p303 PUBSUB NUMPAT
第十九章 事務
19.1 事務的實現
- p306 事務開始
- p306 MULTI命令
- p306 命令入隊
- p307 事務佇列
- p307 mstate屬性
- p309 執行事務
- p309 EXEC命令
19.2 WATCH命令的實現
- p311 使用WATCH命令監視資料庫鍵
- p312 監視機制的觸發
- p313 判斷事務是否安全
- p313 一個完整的WATCH事務執行過程
19.3 事務的ACID性質
- p314 原子性
- p315 一致性
- p316 入隊錯誤
- p317 執行錯誤
- p317 伺服器停機
- p318 隔離性
- p318 耐久性
- p319 no-appendfsync-on-rewrite配置選項對耐久性的影響
第二十章 Lua指令碼
第二十一章 排序
- p344 ALPHA選項
21.1 SORT<key>命令的實現
- p346 伺服器執行SORT numbers命令的詳細步驟
21.2 ALPHA選項的實現
- p348 伺服器執行SORT fruits ALPHA命令的詳細步驟
21.3 ASC選項和DESC選項的實現
21.4 BY選項的實現
- p350 伺服器執行
SORT fruits BY \*-price
命令的詳細步驟
21.5 帶有ALPHA選項的BY選項的實現
- p352 伺服器執行
SORT fruits BY \*-id ALPHA
命令的詳細步驟
21.6 LIMIT選項的實現
- p354 伺服器執行
SORT alphabet ALPHA LIMIT 0 4
命令的詳細步驟
21.7 GET選項的實現
- p356 伺服器執行
SORT studenst ALPHA GET \*-name
命令的詳細步驟
21.8 STORE選項的實現
- p359 伺服器執行
SORT students ALPHA GET \*-name
命令的詳細步驟
21.9 多個選項的執行順序
- p359 選項的的執行順序
- p259 一個SORT命令的執行過程可以分為以下四步
第二十二章 二進位制位陣列
- p362 Redis提供了SETBIT、GETBIT、BITCOUNT、BITOP四個命令用於處理二進位制位陣列
22.1 位陣列的表示
- p363 Redis使用字串物件來表示位陣列
22.2 GETBIT命令的實現
22.3 SETBIT命令的實現
- p367 SETBIT命令的執行示例
- p367 帶擴充套件操作的SETBIT命令示例
22.4 BITCOUNT命令的實現
- p370 二進位制位統計演算法(1):遍歷演算法
- p370 二進位制位統計演算法(2):查表演算法
- p371 二進位制位統計演算法(3):variable-precision SWAR演算法
- p372 計算漢明重量
- p374 二進位制位統計演算法(4):Redis的實現
22.5 BITOP命令的實現
第二十三章 慢查詢日誌
- p379 SLOWLOG GET命令