# 簡介
本書對 Redis 的大多數單機功能以及所有多機功能的實現原理進行了介紹, 展示了這些功能的核心數據結構以及關鍵的算法思想。
通過閱讀本書, 讀者可以快速、有效地了解 Redis 的內部構造以及運作機制, 這些知識可以幫助讀者更好地、也更高效地使用 Redis 。
為了讓本書的內容保持簡單并且容易讀懂, 本書會盡量以高層次的角度來對 Redis 的實現原理進行描述, 如果讀者只是對 Redis 的實現原理感興趣, 但并不想研究 Redis 的源代碼, 那么閱讀本書就足夠了。
另一方面, 如果讀者打算深入了解 Redis 實現原理的底層細節, 本書在?[RedisBook.com](http://redisbook.com/)?提供了一份帶有詳細注釋的 Redis 源代碼, 讀者可以先閱讀本書對某一功能的介紹, 然后再閱讀該功能對應的實現代碼, 這有助于讀者更快地讀懂實現代碼, 也有助于讀者更深入地了解該功能的實現原理。
## 版本說明
本書是基于 Redis 2.9 —— 也即是 Redis 3.0 的開發版來編寫的, 因為 Redis 3.0 的更新主要與 Redis 的多機功能有關, 而 Redis 3.0 的單機功能則與 Redis 2.6 、Redis 2.8 的單機功能基本相同, 所以本書的內容對于使用 Redis 2.6 至 Redis 3.0 的讀者來說應該都是有用的。
另外, 因為 Redis 通常都是漸進地增加新功能, 并且很少會大幅地修改已有的功能, 所以本書的大部分內容對于 Redis 3.0 之后的幾個版本來說, 應該也是有用的。
## 章節編排
本書由《數據結構與對象》、《單機數據庫的實現》、《多機數據庫的實現》、《獨立功能的實現》四個部分組成。
### 第一部分
Redis 數據庫里面的每個鍵值對(key-value pair)都是由對象(object)組成的:
* 其中, 數據庫鍵總是一個字符串對象(string object);
* 而數據庫鍵的值則可以是字符串對象、 列表對象(list object)、 哈希對象(hash object)、 集合對象(set object)、 有序集合對象(sorted set object)這五種對象中的其中一種。
比如說, 執行以下命令將在數據庫中創建一個鍵為字符串對象, 值也為字符串對象的鍵值對:
~~~
redis> SET msg "hello world"
OK
~~~
而執行以下命令將在數據庫中創建一個鍵為字符串對象, 值為列表對象的鍵值對:
~~~
redis> RPUSH numbers 1 3 5 7 9
(integer) 5
~~~
本書的第一部分 —— 也即是《數據結構與對象》部分, 將對以上提到的五種不同類型的對象進行介紹, 剖析這些對象所使用的底層數據結構, 并說明這些數據結構是如何深刻地影響對象的功能和性能的。
### 第二部分
本書的第二部分 —— 也即是《單機數據庫的實現》部分, 對 Redis 實現單機數據庫的方法進行了介紹。
《數據庫》一章對 Redis 數據庫的實現原理進行了介紹: 說明了服務器保存鍵值對的方法, 服務器保存鍵值對過期時間的方法, 以及服務器自動刪除過期鍵值對的方法, 等等。
《RDB 持久化》和《AOF 持久化》兩章分別介紹了 Redis 兩種不同的持久化方式的實現原理: 說明了服務器根據數據庫來生成持久化文件的方法, 服務器根據持久化文件來還原數據庫的方法, 以及?BGSAVE?命令和?BGREWRITEAOF?命令的實現原理, 等等。
《事件》一章對 Redis 的文件事件和時間事件進行了介紹:
* 文件事件主要用于應答(accept)客戶端的連接請求, 接收客戶端發送的命令請求, 以及向客戶端返回命令回復;
* 而時間事件則主要用于執行?`redis.c/serverCron`?函數 —— 這個函數通過執行常規的維護和管理操作來保持 Redis 服務器的正常運作, 一些重要的定時操作也是由這個函數負責觸發的。
《客戶端》一章對 Redis 服務器維護和管理客戶端狀態的方法進行了介紹: 列舉了客戶端狀態包含的各個屬性, 說明了客戶端的輸入緩沖區和輸出緩沖區的實現方法, 以及 Redis 服務器創建和銷毀客戶端狀態的條件, 等等。
《服務器》一章對單機 Redis 服務器的運作機制進行了介紹: 詳細地說明了服務器處理命令請求的步驟, 解釋了?`serverCron`?函數所做的工作, 并講解了 Redis 服務器的初始化過程。
### 第三部分
本書的第三部分 —— 也即是《多機數據庫的實現》部分, 對 Redis 的 Sentinel 、復制(replication)、集群(cluster)三個多機功能進行了介紹。
《Sentinel》一章對 Redis Sentinel 的實現原理進行了介紹: 說明了 Sentinel 監視服務器的方法, Sentinel 判斷服務器是否下線的方法, 以及 Sentinel 對下線服務器進行故障轉移的方法, 等等。
《復制》一章對 Redis 的主從復制功能(master-slave replication)的實現原理進行了介紹: 說明了當用戶指定一個服務器(從服務器)去復制另一個服務器(主服務器)時, 主從服務器之間執行了什么操作, 進行了什么數據交互, 諸如此類。
《集群》一章對 Redis 集群的實現原理進行了介紹: 說明了節點(node)的構建方法, 節點處理命令請求的方法, 轉發(redirection)錯誤的實現方法, 以及各個節點之間進行通訊的方法, 等等。
### 第四部分
本書的第四部分 —— 也即是《獨立功能的實現》部分, 對 Redis 中各個相對獨立的功能模塊進行了介紹。
《發布與訂閱》一章對?PUBLISH?、?SUBSCRIBE?、?PUBSUB?等命令的實現原理進行了介紹, 解釋了 Redis 的發布與訂閱功能是如何實現的。
《事務》一章對?MULTI?、?EXEC?、?WATCH?等命令的實現原理進行了介紹, 解釋了 Redis 的事務是如何實現的, 并說明了 Redis 的事務對 ACID 性質的支持程度。
《Lua 腳本》一章對?EVAL?、?EVALSHA?、?SCRIPT_LOAD?等命令的實現原理進行了介紹, 解釋了 Redis 服務器是如何執行和管理用戶傳入的 Lua 腳本的; 這一章還對 Redis 服務器構建 Lua 環境的過程, 以及主從服務器之間復制 Lua 腳本的方法進行了介紹。
《排序》一章對?SORT?命令、 以及?SORT?命令所有可用選項(比如?`DESC`?、?`ALPHA`?、?`GET`?,等等)的實現原理進行了介紹, 并說明了當SORT?命令帶有多個選項時, 不同選項執行的先后順序。
《二進制位數組》一章對 Redis 保存二進制位數組的方法進行了介紹, 并說明了?GETBIT?、?SETBIT?、?BITCOUNT?、?BITOP?這幾個二進制位數組操作命令的實現原理。
《慢查詢日志》一章對 Redis 創建和保存慢查詢日志(slow log)的方法進行了介紹, 并說明了?SLOWLOG GET?、?SLOWLOG LEN?、SLOWLOG RESET?等慢查詢日志操作命令的實現原理。
《監視器》一章介紹了將客戶端變為監視器(monitor)的方法, 以及服務器在處理命令請求時, 向監視器發送命令信息的方法。
## 推薦的閱讀方法
因為 Redis 的單機功能是多機功能的子集, 所以無論讀者使用的是單機模式的 Redis , 還是多機模式的 Redis , 都應該閱讀本書的第一部分和第二部分, 也即是《數據結構與對象》部分和《單機數據庫的實現》部分, 這兩個部分包含的知識是所有 Redis 使用者都必然會用到的。
如果讀者要使用 Redis 的多機功能, 那么在閱讀本書的第一部分和第二部分之后, 應該接著閱讀本書的第三部分, 也即是《多機數據庫的實現》部分; 相反地, 如果讀者只使用 Redis 的單機功能, 那么可以跳過第三部分, 直接閱讀第四部分。
本書的前三個部分都是以自底向上(bottom-up)的方式來寫的, 也就是說, 排在后面的章節會假設讀者已經讀過了排在前面的章節: 如果一個概念在前面的章節已經介紹過, 那么后面的章節就不會再重復介紹這個概念, 所以讀者最好按順序閱讀這三部分的各個章節。
本書的第四部分 —— 也即是《獨立功能的實現》部分包含的各章是完全獨立的, 讀者可以按自己的興趣來挑選要讀的章節。
在本書的第四部分中, 除了《Lua 腳本》一章的其中一節有涉及多機功能的內容之外, 其他章節都沒有涉及多機功能的內容, 所以第四部分的大部分內容都可以在只閱讀了本書第一部分和第二部分的情況下閱讀。
圖 1-1 對上面描述的閱讀方法進行了總結。

## 行文規則
### 名字引用規則
在第一次引用 Redis 源代碼文件?`file`?中的名字?`name`?時, 本書使用?`file/name`?格式: 比如?`redis.c/main`?表示?`redis.c`?文件中的?`main`函數, 而?`redis.h/redisDb`?則表示?`redis.h`?文件中的?`redisDb`?結構, 諸如此類。
另外, 在第一次引用標準庫頭文件?`file`?中的名字?`name`?時, 本書使用?`<file>/name`?格式: 比如?`<unistd.h>/write`?表示?`unistd.h`?頭文件的?`write`?函數, 而?`<stdio.h>/printf`?則表示?`stdio.h`?頭文件的?`printf`?函數, 諸如此類。
在第一次引用某個名字之后, 本書就會去掉名字前綴的文件名, 直接使用名字本身。
舉個例子, 當本書第一次引用?`redis.h`?文件的?`redisDb`?結構的時候, 本書會使用?`redis.h/redisDb`?格式, 而之后再次引用?`redisDb`?結構時, 本書只使用名字?`redisDb`?。
### 結構引用規則
本書使用?`struct.property`?格式來引用?`struct`?結構的?`property`?屬性: 比如?`redisDb.id`?表示?`redisDb`?結構的?`id`?屬性, 而`redisDb.expires`?則表示?`redisDb`?結構的?`expires`?屬性, 諸如此類。
### 算法規則
除非有額外說明, 否則本書列出的算法復雜度一律為最壞情形下的算法復雜度。
### 代碼規則
本書使用 C 語言和 Python 語言來展示代碼:
* 在描述數據結構以及比較簡短的代碼時, 本書通常會直接粘貼 Redis 的源代碼, 也即是 C 語言代碼。
* 相反地, 當需要使用代碼來描述比較長或者比較復雜的程序時, 本書通常會使用 Python 語言來表示偽代碼。
本書展示的 Python 偽代碼中通常會包含?`server`?和?`client`?兩個全局變量: 其中?`server`?表示服務器狀態(`redis.h/redisServer`?結構的實例), 而?`client`?則表示正在執行操作的客戶端狀態(`redis.h/redisClient`?結構的實例)。
## 配套網站
本書帶有配套網站?[RedisBook.com](http://redisbook.com/)?, 這個網站記錄了本書的最新消息, 并且提供了附帶詳細注釋的 Redis 源代碼可供下載, 讀者也可以通過這個網站查看和反饋本書的勘誤, 或者發表與本書有關的問題、意見、以及建議。
- 介紹
- 前言
- 致謝
- 簡介
- 第一部分:數據結構與對象
- 簡單動態字符串
- SDS 的定義
- SDS 與 C 字符串的區別
- SDS API
- 重點回顧
- 參考資料
- 鏈表
- 鏈表和鏈表節點的實現
- 鏈表和鏈表節點的 API
- 重點回顧
- 字典
- 字典的實現
- 哈希算法
- 解決鍵沖突
- rehash
- 漸進式 rehash
- 字典 API
- 重點回顧
- 跳躍表
- 跳躍表的實現
- 跳躍表 API
- 重點回顧
- 整數集合
- 整數集合的實現
- 升級
- 升級的好處
- 降級
- 整數集合 API
- 重點回顧
- 壓縮列表
- 壓縮列表的構成
- 壓縮列表節點的構成
- 連鎖更新
- 壓縮列表 API
- 重點回顧
- 對象
- 對象的類型與編碼
- 字符串對象
- 列表對象
- 哈希對象
- 集合對象
- 有序集合對象
- 類型檢查與命令多態
- 內存回收
- 對象共享
- 對象的空轉時長
- 重點回顧
- 第二部分:單機數據庫的實現
- 數據庫
- 數據庫鍵空間
- 重點回顧
- RDB 持久化
- RDB 文件結構
- 重點回顧
- AOF 持久化
- AOF 持久化的實現
- 重點回顧
- 事件
- 文件事件
- 重點回顧
- 參考資料
- 客戶端
- 客戶端屬性
- 重點回顧
- 服務器
- 命令請求的執行過程
- 重點回顧
- 第三部分:多機數據庫的實現
- 復制
- 舊版復制功能的實現
- 重點回顧
- Sentinel
- 啟動并初始化 Sentinel
- 重點回顧
- 參考資料
- 集群
- 節點
- 重點回顧
- 第四部分:獨立功能的實現
- 發布與訂閱
- 頻道的訂閱與退訂
- 重點回顧
- 參考資料
- 事務
- 事務的實現
- 重點回顧
- Lua 腳本
- 創建并修改 Lua 環境
- 重點回顧
- 排序
- SORT <key> 命令的實現
- 重點回顧
- 二進制位數組
- GETBIT 命令的實現
- 重點回顧
- 慢查詢日志
- 慢查詢記錄的保存
- 慢查詢日志的閱覽和刪除
- 添加新日志
- 重點回顧
- 監視器
- 成為監視器
- 向監視器發送命令信息
- 重點回顧
- 源碼、相關資源和勘誤