如何閱讀 Redis 源碼?(轉)


在這篇文章中, 我將向大家介紹一種我認為比較合理的 Redis 源碼閱讀順序, 希望可以給對 Redis 有興趣并打算閱讀 Redis 源碼的朋友帶來一點幫助。
第 1 步:閱讀數據結構實現
剛開始閱讀 Redis 源碼的時候, 最好從數據結構的相關文件開始讀起, 因為這些文件和 Redis 中的其他部分耦合最少, 并且這些文件所實現的數據結構在大部分算法書上都可以了解到, 所以從這些文件開始讀是最輕松的、難度也是最低的。
下表列出了 Redis 源碼中, 各個數據結構的實現文件:

文件
內容

sds.h
和 sds.c

Redis 的動態字符串實現。

adlist.h
和 adlist.c

Redis 的雙端鏈表實現。

dict.h
和 dict.c

Redis 的字典實現。

redis.h
中的 zskiplist
結構和 zskiplistNode
結構, 以及 t_zset.c
中所有以zsl
開頭的函數, 比如 zslCreate
、 zslInsert
、 zslDeleteNode
,等等。
Redis 的跳躍表實現。

hyperloglog.c
中的 hllhdr
結構, 以及所有以 hll
開頭的函數。
Redis 的 HyperLogLog 實現。

第 2 步:閱讀內存編碼數據結構實現
在閱讀完和數據結構有關的文件之后, 接下來就應該閱讀內存編碼(encoding)數據結構了。
和普通的數據結構一樣, 內存編碼數據結構基本上是獨立的, 不和其他模塊耦合, 但是區別在于:
上一步要讀的數據結構, 比如雙端鏈表、字典、HyperLogLog, 在算法書上或者相關的論文上都可以找到資料介紹。
而內存編碼數據結構卻不容易找到相關的資料, 因為這些數據結構都是 Redis 為了節約內存而專門開發出來的, 換句話說, 這些數據結構都是特制(adhoc)的, 除了 Redis 源碼中的文檔之外, 基本上找不到其他資料來了解這些特制的數據結構。

不過話又說回來, 雖然內存編碼數據結構是 Redis 特制的, 但它們基本都和內存分配、指針操作、位操作這些底層的東西有關, 讀者只要認真閱讀源碼中的文檔, 并在有需要時, 畫圖來分析這些數據結構, 那么要完全理解這些內存編碼數據結構的運作原理并不難, 當然這需要花一些功夫。
下表展示了 Redis 源碼中, 各個內存編碼數據結構的實現文件:

文件
內容

intset.h
和 intset.c

整數集合(intset)數據結構。

ziplist.h
和 ziplist.c

壓縮列表(zip list)數據結構。

第 3 步:閱讀數據類型實現
在完成以上兩個閱讀步驟之后, 我們就讀完了 Redis 六種不同類型的鍵(字符串、散列、列表、集合、有序集合、HyperLogLog)的所有底層實現結構了。
接下來, 為了知道 Redis 是如何通過以上提到的數據結構來實現不同類型的鍵, 我們需要閱讀實現各個數據類型的文件, 以及 Redis 的對象系統文件, 這些文件包括:

文件
內容

object.c

Redis 的對象(類型)系統實現。

t_string.c

字符串鍵的實現。

t_list.c

列表鍵的實現。

t_hash.c

散列鍵的實現。

t_set.c

集合鍵的實現。

t_zset.c
中除 zsl
開頭的函數之外的所有函數。
有序集合鍵的實現。

hyperloglog.c
中所有以 pf
開頭的函數。
HyperLogLog 鍵的實現。

第 4 步:閱讀數據庫實現相關代碼
在讀完了 Redis 使用所有底層數據結構, 以及 Redis 是如何使用這些數據結構來實現不同類型的鍵之后, 我們就可以開始閱讀 Redis 里面和數據庫有關的代碼了, 它們分別是:

文件
內容

redis.h
文件中的 redisDb
結構, 以及 db.c
文件。
Redis 的數據庫實現。

notify.c

Redis 的數據庫通知功能實現代碼。

rdb.h
和 rdb.c

Redis 的 RDB 持久化實現代碼。

aof.c

Redis 的 AOF 持久化實現代碼。

選讀
Redis 有一些獨立的功能模塊, 這些模塊可以在完成第 4 步之后閱讀, 它們包括:

文件
內容

redis.h
文件的 pubsubPattern
結構,以及 pubsub.c
文件。
發布與訂閱功能的實現。

redis.h
文件的 multiState
結構以及 multiCmd
結構, multi.c
文件。
事務功能的實現。

sort.c

SORT
命令的實現。

bitops.c

GETBIT
、 SETBIT
等二進制位操作命令的實現。

第 5 步:閱讀客戶端和服務器的相關代碼
在閱讀完數據庫實現代碼, 以及 RDB 和 AOF 兩種持久化的代碼之后, 我們可以開始閱讀客戶端和 Redis 服務器本身的實現代碼, 和這些代碼有關的文件是:

文件
內容

ae.c
,以及任意一個 ae_*.c
文件(取決于你所使用的多路復用庫)。
Redis 的事件處理器實現(基于 Reactor 模式)。

networking.c

Redis 的網絡連接庫,負責發送命令回復和接受命令請求, 同時也負責創建/銷毀客戶端, 以及通信協議分析等工作。

redis.h
和 redis.c
中和單機 Redis 服務器有關的部分。
單機 Redis 服務器的實現。

如果讀者能完成以上 5 個閱讀步驟的話, 那么恭喜你, 你已經了解了單機的 Redis 服務器是怎樣處理命令請求和返回命令回復, 以及是 Redis 怎樣操作數據庫的了, 這是 Redis 最重要的部分, 也是之后繼續閱讀多機功能的基礎。
選讀
Redis 有一些獨立的功能模塊, 這些模塊可以在完成第 5 步之后閱讀, 它們包括:

文件
內容

scripting.c

Lua 腳本功能的實現。

slowlog.c

慢查詢功能的實現。

monitor.c

監視器功能的實現。

第 6 步:閱讀多機功能的實現
在弄懂了 Redis 的單機服務器是怎樣運作的之后, 就可以開始閱讀 Redis 多機功能的實現代碼了, 和這些功能有關的文件為:

文件
內容

replication.c

復制功能的實現代碼。

sentinel.c

Redis Sentinel 的實現代碼。

cluster.c

Redis 集群的實現代碼。

注意, 因為 Redis Sentinel 用到了復制功能的代碼, 而集群又用到了復制和 Redis Sentinel 的代碼, 所以在閱讀這三個模塊的時候, 記得先閱讀復制模塊, 然后閱讀 Sentinel 模塊, 最后才閱讀集群模塊, 這樣理解起來就會更得心應手。
如果你連這三個模塊都讀完了的話, 那么恭喜你, 你已經讀完了 Redis 單機功能和多機功能的所有代碼了!
下圖總結了本文介紹的閱讀順序:
encoding_datastruct -> object -> db -> client_and_server -> multi_server}" style="border: 0px; max-width: 100%;">

結語
Redis 的設計非常簡潔、優美、精巧和高效, 任何人只要愿意去閱讀它的代碼的話, 應該都會有所收獲的。
希望這篇文章能夠給想要閱讀 Redis 代碼的朋友們帶來一些幫助, 也歡迎各位隨時和我討論 Redis 源碼方面的問題, 或者跟我分享各位閱讀 Redis 源碼的心得和經驗。
另外我的 Redis 源碼注釋 項目以及 《Redis 設計與實現》 一書對于理解 Redis 的源代碼應該也會有所幫助, 有興趣的朋友可以自行了解該項目/書本。

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

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,264評論 25 708
  • 轉載地址:http://gnucto.blog.51cto.com/3391516/998509 Redis與Me...
    Ddaidai閱讀 21,466評論 0 82
  • 后悔沒有早一點讀到三毛。 沒有太過絢爛的辭藻,沒有嬌柔造作的排比,可是景象和性情就這么如棉絮般細細地抽出來。時而輕...
    Jinspiration閱讀 390評論 2 2