如何閱讀 Redis 源碼

在這篇文章中, 將向大家介紹一種比較合理的 Redis 源碼閱讀順序, 希望可以給對 Redis 有興趣并打算閱讀 Redis 源碼的朋友帶來一點幫助。

第 1 步:閱讀數(shù)據(jù)結(jié)構(gòu)實現(xiàn)

剛開始閱讀 Redis 源碼的時候, 最好從數(shù)據(jù)結(jié)構(gòu)的相關(guān)文件開始讀起, 因為這些文件和 Redis 中的其他部分耦合最少, 并且這些文件所實現(xiàn)的數(shù)據(jù)結(jié)構(gòu)在大部分算法書上都可以了解到, 所以從這些文件開始讀是最輕松的、難度也是最低的。

下表列出了 Redis 源碼中, 各個數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)文件:

文件內(nèi)容

sds.h?和?sds.c????Redis 的動態(tài)字符串實現(xiàn)。

adlist.h?和?adlist.c????Redis 的雙端鏈表實現(xiàn)。

dict.h?和?dict.c????Redis 的字典實現(xiàn)。

redis.h?中的?zskiplist?結(jié)構(gòu)和?zskiplistNode?結(jié)構(gòu), 以及?t_zset.c?中所有以?zsl?開頭的函數(shù), 比如?zslCreate?、?zslInsert、?zslDeleteNode 等等。Redis 的跳躍表實現(xiàn)。

hyperloglog.c?中的?hllhdr?結(jié)構(gòu), 以及所有以?hll?開頭的函數(shù)。Redis 的HyperLogLog 實現(xiàn)。

第 2 步:閱讀內(nèi)存編碼數(shù)據(jù)結(jié)構(gòu)實現(xiàn)

在閱讀完和數(shù)據(jù)結(jié)構(gòu)有關(guān)的文件之后, 接下來就應(yīng)該閱讀內(nèi)存編碼(encoding)數(shù)據(jù)結(jié)構(gòu)了。

和普通的數(shù)據(jù)結(jié)構(gòu)一樣, 內(nèi)存編碼數(shù)據(jù)結(jié)構(gòu)基本上是獨立的, 不和其他模塊耦合, 但是區(qū)別在于:

上一步要讀的數(shù)據(jù)結(jié)構(gòu), 比如雙端鏈表、字典、HyperLogLog, 在算法書上或者相關(guān)的論文上都可以找到資料介紹。

而內(nèi)存編碼數(shù)據(jù)結(jié)構(gòu)卻不容易找到相關(guān)的資料, 因為這些數(shù)據(jù)結(jié)構(gòu)都是 Redis 為了節(jié)約內(nèi)存而專門開發(fā)出來的, 換句話說, 這些數(shù)據(jù)結(jié)構(gòu)都是特制(adhoc)的, 除了 Redis 源碼中的文檔之外, 基本上找不到其他資料來了解這些特制的數(shù)據(jù)結(jié)構(gòu)。

不過話又說回來, 雖然內(nèi)存編碼數(shù)據(jù)結(jié)構(gòu)是 Redis 特制的, 但它們基本都和內(nèi)存分配、指針操作、位操作這些底層的東西有關(guān), 讀者只要認真閱讀源碼中的文檔, 并在有需要時, 畫圖來分析這些數(shù)據(jù)結(jié)構(gòu), 那么要完全理解這些內(nèi)存編碼數(shù)據(jù)結(jié)構(gòu)的運作原理并不難, 當然這需要花一些功夫。

下表展示了 Redis 源碼中, 各個內(nèi)存編碼數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)文件:

文件內(nèi)容

intset.h?和?intset.c整數(shù)集合(intset)數(shù)據(jù)結(jié)構(gòu)。

ziplist.h?和?ziplist.c壓縮列表(zip list)數(shù)據(jù)結(jié)構(gòu)。

第 3 步:閱讀數(shù)據(jù)類型實現(xiàn)

在完成以上兩個閱讀步驟之后, 我們就讀完了 Redis 六種不同類型的鍵(字符串、散列、列表、集合、有序集合、HyperLogLog)的所有底層實現(xiàn)結(jié)構(gòu)了。

接下來, 為了知道 Redis 是如何通過以上提到的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)不同類型的鍵, 我們需要閱讀實現(xiàn)各個數(shù)據(jù)類型的文件, 以及 Redis 的對象系統(tǒng)文件, 這些文件包括:

文件內(nèi)容

object.c? ? Redis 的對象(類型)系統(tǒng)實現(xiàn)。

t_string.c????字符串鍵的實現(xiàn)。

t_list.c????列表鍵的實現(xiàn)。

t_hash.c????散列鍵的實現(xiàn)。

t_set.c????集合鍵的實現(xiàn)。

t_zset.c?????中除?zsl?開頭的函數(shù)之外的所有函數(shù)。有序集合鍵的實現(xiàn)。

hyperloglog.c?????中所有以?pf?開頭的函數(shù)。HyperLogLog 鍵的實現(xiàn)。

第 4 步:閱讀數(shù)據(jù)庫實現(xiàn)相關(guān)代碼

在讀完了 Redis 使用所有底層數(shù)據(jù)結(jié)構(gòu), 以及 Redis 是如何使用這些數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)不同類型的鍵之后, 我們就可以開始閱讀 Redis 里面和數(shù)據(jù)庫有關(guān)的代碼了, 它們分別是:

文件內(nèi)容

redis.h?????文件中的?redisDb?結(jié)構(gòu), 以及?db.c?文件。Redis 的數(shù)據(jù)庫實現(xiàn)。

notify.c????Redis 的數(shù)據(jù)庫通知功能實現(xiàn)代碼。

rdb.h?和?rdb.c????Redis 的 RDB 持久化實現(xiàn)代碼。

aof.c????Redis 的 AOF 持久化實現(xiàn)代碼。

選讀

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

文件內(nèi)容

redis.h?文件的?pubsubPattern?結(jié)構(gòu),以及?pubsub.c?文件。發(fā)布與訂閱功能的實現(xiàn)。

redis.h?文件的?multiState?結(jié)構(gòu)以及?multiCmd?結(jié)構(gòu),?multi.c?文件。事務(wù)功能的實現(xiàn)。

sort.c????SORT?命令的實現(xiàn)。

bitops.c????GETBIT?、?SETBIT?等二進制位操作命令的實現(xiàn)。

第 5 步:閱讀客戶端和服務(wù)器的相關(guān)代碼

在閱讀完數(shù)據(jù)庫實現(xiàn)代碼, 以及 RDB 和 AOF 兩種持久化的代碼之后, 我們可以開始閱讀客戶端和 Redis 服務(wù)器本身的實現(xiàn)代碼, 和這些代碼有關(guān)的文件是:

文件內(nèi)容

事件處理模塊 ae.c/ae_epoll.c/ae_evport.c/ae_kqueue.c/ae_select.c。以及任意一個?ae_*.c?文件(取決于你所使用的多路復用庫)。Redis 的事件處理器實現(xiàn)(基于 Reactor 模式)。

網(wǎng)路鏈接庫 anet.c和networking.c的網(wǎng)絡(luò)連接庫,負責發(fā)送命令回復和接受命令請求, 同時也負責創(chuàng)建/銷毀客戶端, 以及通信協(xié)議分析等工作。

服務(wù)器端 redis.c客戶端 redis-cli.c

如果讀者能完成以上 5 個閱讀步驟的話, 那么恭喜你, 你已經(jīng)了解了單機的 Redis 服務(wù)器是怎樣處理命令請求和返回命令回復, 以及是 Redis 怎樣操作數(shù)據(jù)庫的了, 這是 Redis 最重要的部分, 也是之后繼續(xù)閱讀多機功能的基礎(chǔ)。

選讀

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

文件內(nèi)容

scripting.c????Lua 腳本功能的實現(xiàn)。

slowlog.c????慢查詢功能的實現(xiàn)。

monitor.c????監(jiān)視器功能的實現(xiàn)。

第 6 步:閱讀多機功能的實現(xiàn)

在弄懂了 Redis 的單機服務(wù)器是怎樣運作的之后, 就可以開始閱讀 Redis 多機功能的實現(xiàn)代碼了, 和這些功能有關(guān)的文件為:

文件內(nèi)容

replication.c????復制功能的實現(xiàn)代碼。

sentinel.c????Redis Sentinel 的實現(xiàn)代碼。

cluster.c????Redis 集群的實現(xiàn)代碼。

注意, 因為 Redis Sentinel 用到了復制功能的代碼, 而集群又用到了復制和 Redis Sentinel 的代碼, 所以在閱讀這三個模塊的時候, 記得先閱讀復制模塊, 然后閱讀 Sentinel 模塊, 最后才閱讀集群模塊, 這樣理解起來就會更得心應(yīng)手。

如果你連這三個模塊都讀完了的話, 那么恭喜你, 你已經(jīng)讀完了 Redis 單機功能和多機功能的所有代碼了!

其他代碼文件介紹

關(guān)于測試方面的文件有:

memtest.c ????內(nèi)存檢測

redis_benchmark.c ????用于redis性能測試的實現(xiàn)。

redis_check_aof.c ????用于更新日志檢查的實現(xiàn)。

redis_check_dump.c ????用于本地數(shù)據(jù)庫檢查的實現(xiàn)。

testhelp.c ????一個C風格的小型測試框架。

一些工具類的文件如下:

bitops.c ????GETBIT、SETBIT 等二進制位操作命令的實現(xiàn)

debug.c ????用于調(diào)試時使用

endianconv.c ????高低位轉(zhuǎn)換,不同系統(tǒng),高低位順序不同

help.h ????輔助于命令的提示信息

lzf_c.c ????壓縮算法系列

lzf_d.c ????壓縮算法系列

rand.c ????用于產(chǎn)生隨機數(shù)

release.c ????用于發(fā)布時使用

sha1.c sha????加密算法的實現(xiàn)

util.c ????通用工具方法

crc64.c ????循環(huán)冗余校驗

sort.c ????SORT命令的實現(xiàn)


一些封裝類的代碼實現(xiàn):

bio.c ????background I/O的意思,開啟后臺線程用的

latency.c ????延遲類

migrate.c ????命令遷移類,包括命令的還原遷移等

pqsort.c ????排序算法類

rio.c ????redis定義的一個I/O類

syncio.c ????用于同步Socket和文件I/O操作

下圖總結(jié)了本文介紹的閱讀順序:



結(jié)語

Redis 的設(shè)計非常簡潔、優(yōu)美、精巧和高效, 任何人只要愿意去閱讀它的代碼的話, 應(yīng)該都會有所收獲的。

希望這篇文章能夠給想要閱讀 Redis 代碼的朋友們帶來一些幫助, 也歡迎各位隨時留言討論 Redis 源碼方面的問題, 或者跟我分享各位閱讀 Redis 源碼的心得和經(jīng)驗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在這篇文章中, 我將向大家介紹一種我認為比較合理的 Redis 源碼閱讀順序, 希望可以給對 Redis 有興趣并...
    柏樹_Jeff閱讀 55,765評論 2 18
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,632評論 19 139
  • 超強、超詳細Redis入門教程 轉(zhuǎn)載2017年03月04日 16:20:02 16916 轉(zhuǎn)載自: http://...
    邵云濤閱讀 17,633評論 3 313
  • 我慢慢從刺耳讓人不喜的鬧鐘聲里醒來,但是我不想起床,我也不想把鬧鐘關(guān)掉,我聽著它在響,平常我應(yīng)該做什么了呢。 應(yīng)該...
    周周昭昭閱讀 242評論 0 0
  • 文 | 晨光花開 特別佩服現(xiàn)在的廣告運營商。 因為他們已經(jīng)滲透在我們生活的方方面面。 從手中用的東西,到眼里看的樣...
    晨光花開閱讀 221評論 0 2

友情鏈接更多精彩內(nèi)容