Redis源碼剖析--源碼結構解析

如何閱讀 Redis 源碼?

找工做那會兒,看了黃建宏老師的《Redis設計與實現》,對redis的部分實現有了一個簡明的認識。在面試過程當中,redis確實成爲了面試官考覈個人一個亮點,剛好之後的工做又與redis有着千絲萬縷的聯繫,因而就想趁着畢業前的這段時間把redis的源代碼研究一下,爲之後的工做打個良好的基礎。 html

Redis簡介

redis全稱REmote DIctionary Server,是一個由Salvatore Sanfilippo寫的高性能key-value存儲系統,其徹底開源免費,遵照BSD協議。Redis與其餘key-value緩存產品(如memcache)有如下幾個特色。 
+ Redis支持數據的持久化,能夠將內存中的數據保存在磁盤中,重啓的時候能夠再次加載進行使用。 
+ Redis不單單支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。 
+ Redis支持數據的備份,即master-slave模式的數據備份。面試

Redis的性能極高且擁有豐富的數據類型,同時,Redis全部操做都是原子性的,也支持對幾個操做合併後原子性的執行。另外,Redis有豐富的擴展特性,它支持publish/subscribe, 通知,key 過時等等特性。redis

Redis更爲優秀的地方在於,它的代碼風格極其精簡,整個源碼只有23000行,頗有利於閱讀和賞析!還在等什麼呢?Start!算法

如何獲取Redis源碼?

redis是徹底開源的,其源代碼能夠在直接在官網上獲取(目前最新版本是3.2.5)。執行如下指令:數據庫

cd ... // 這裏打開你存放redis的文件夾
wget http://download.redis.io/releases/redis-3.2.5.tar.gz
tar zxvf redis-3.2.5.tar.gz

此時,進入解壓後的redis目錄下的src文件夾,redis的全部源代碼都存放在此。centos

[root@VM_123_20_centos redis-3.2.5]# cd src/
[root@VM_123_20_centos src]# ls
Makefile      crc64.h        mkreleasehdr.sh    redis-cli.o     sort.o
Makefile.dep  crc64.o        multi.c            redis-sentinel  sparkline.c
adlist.c      db.c           multi.o            redis-server    sparkline.h
adlist.h      db.o           networking.c       redis-trib.rb   sparkline.o
adlist.o      debug.c        networking.o       redisassert.h   syncio.c
ae.c          debug.o        notify.c           release.c       syncio.o
ae.h          debugmacro.h   notify.o           release.h       t_hash.c
ae.o          dict.c         object.c           release.o       t_hash.o
ae_epoll.c    dict.h         object.o           replication.c   t_list.c
ae_evport.c   dict.o         pqsort.c           replication.o   t_list.o
ae_kqueue.c   endianconv.c   pqsort.h           rio.c           t_set.c
ae_select.c   endianconv.h   pqsort.o           rio.h           t_set.o
anet.c        endianconv.o   pubsub.c           rio.o           t_string.c
anet.h        fmacros.h      pubsub.o           scripting.c     t_string.o
anet.o        geo.c          quicklist.c        scripting.o     t_zset.c
aof.c         geo.h          quicklist.h        sds.c           t_zset.o
aof.o         geo.o          quicklist.o        sds.h           testhelp.h
asciilogo.h   help.h         rand.c             sds.o           util.c
bio.c         hyperloglog.c  rand.h             sdsalloc.h      util.h
bio.h         hyperloglog.o  rand.o             sentinel.c      util.o
bio.o         intset.c       rdb.c              sentinel.o      valgrind.sup
bitops.c      intset.h       rdb.h              server.c        version.h
bitops.o      intset.o       rdb.o              server.h        ziplist.c
blocked.c     latency.c      redis-benchmark    server.o        ziplist.h
blocked.o     latency.h      redis-benchmark.c  setproctitle.c  ziplist.o
cluster.c     latency.o      redis-benchmark.o  setproctitle.o  zipmap.c
cluster.h     lzf.h          redis-check-aof    sha1.c          zipmap.h
cluster.o     lzfP.h         redis-check-aof.c  sha1.h          zipmap.o
config.c      lzf_c.c        redis-check-aof.o  sha1.o          zmalloc.c
config.h      lzf_c.o        redis-check-rdb    slowlog.c       zmalloc.h
config.o      lzf_d.c        redis-check-rdb.c  slowlog.h       zmalloc.o
crc16.c       lzf_d.o        redis-check-rdb.o  slowlog.o
crc16.o       memtest.c      redis-cli          solarisfixes.h
crc64.c       memtest.o      redis-cli.c        sort.c

源代碼結構解析

看了上面src目錄下的文件,簡直讓人眼花繚亂。這裏不得不批評如下redis的做者啊,都沒有整理一下源代碼,通通都放在一個文件夾下。緩存

正所謂不打無準備的仗,拿到源碼以後,咱們首先要對這些文件進行一個分類,來規劃一下咱們的閱讀順序。這裏介紹一下在網上看到的源碼閱讀方法(摘自redis源碼解析)。sass

  • 自底向上:從耦合關係最小的模塊開始讀,而後逐漸過分到關係緊密的模塊。就好像寫程序的測試同樣,先從單元測試開始,而後纔到功能測試。
  • 從功能入手:經過文件名(模塊名)和函數名,快速定位到一個功能的具體實現,而後追蹤整個實現的運做流程,從而瞭解該功能的實現方式。
  • 自頂向下:從程序的 main() 函數,或者某個特別大的調用者函數爲入口,以深度優先或者廣度優先的方式閱讀它的源碼。

另外,按照黃健宏老師《如何閱讀 Redis 源碼?》一文中介紹的redis閱讀方法,基本上能夠將上述文件進行合理的拆分,以便於對其進行一一攻破。服務器

按照上圖對Redis源碼的模塊劃分,初步肯定一下源碼的學習路線以下:數據結構

第一階段

閱讀Redis的數據結構部分,基本位於以下文件中: 
+ 內存分配 zmalloc.c和zmalloc.h 
+ 動態字符串 sds.h和sds.c 
+ 雙端鏈表 adlist.c和adlist.h 
+ 字典 dict.h和dict.c 
+ 跳躍表 server.h文件裏面關於zskiplist結構和zskiplistNode結構,以及t_zset.c中全部zsl開頭的函數,好比 zslCreate、zslInsert、zslDeleteNode等等。 
+ 日誌類型 hyperloglog.c 中的 hllhdr 結構, 以及全部以 hll 開頭的函數

第二階段

熟悉Redis的內存編碼結構 
+ 整數集合數據結構 intset.h和intset.c 
+ 壓縮列表數據結構 ziplist.h和ziplist.c

第三階段

熟悉Redis數據類型的實現 
+ 對象系統 object.c 
+ 字符串鍵 t_string.c 
+ 列表建 t_list.c 
+ 散列鍵 t_hash.c 
+ 集合鍵 t_set.c 
+ 有序集合鍵 t_zset.c中除 zsl 開頭的函數以外的全部函數 
+ HyperLogLog鍵 hyperloglog.c中全部以pf開頭的函數

第四階段

熟悉Redis數據庫的實現 
+ 數據庫實現 redis.h文件中的redisDb結構,以及db.c文件 
+ 通知功能 notify.c 
+ RDB持久化 rdb.c 
+ AOF持久化 aof.c

以及一些獨立功能模塊的實現 
+ 發佈和訂閱 redis.h文件的pubsubPattern結構,以及pubsub.c文件 
+ 事務 redis.h文件的multiState結構以及multiCmd結構,multi.c文件

第五階段

熟悉客戶端和服務器端的代碼實現 
+ 事件處理模塊 ae.c/ae_epoll.c/ae_evport.c/ae_kqueue.c/ae_select.c 
+ 網路連接庫 anet.c和networking.c 
+ 服務器端 redis.c 
+ 客戶端 redis-cli.c

這個時候能夠閱讀下面的獨立功能模塊的代碼實現 
+ lua腳本 scripting.c 
+ 慢查詢 slowlog.c 
+ 監視 monitor.c

第六階段

這一階段主要是熟悉Redis多機部分的代碼實現

  • 複製功能 replication.c
  • Redis Sentinel sentinel.c
  • 集羣 cluster.c

其餘代碼文件介紹

關於測試方面的文件有: 
+ memtest.c 內存檢測 
+ redis_benchmark.c 用於redis性能測試的實現。 
+ redis_check_aof.c 用於更新日誌檢查的實現。 
+ redis_check_dump.c 用於本地數據庫檢查的實現。 
+ testhelp.c 一個C風格的小型測試框架。

一些工具類的文件以下: 
+ bitops.c GETBIT、SETBIT 等二進制位操做命令的實現 
+ debug.c 用於調試時使用 
+ endianconv.c 高低位轉換,不一樣系統,高低位順序不一樣 
+ help.h 輔助於命令的提示信息 
+ lzf_c.c 壓縮算法系列 
+ lzf_d.c 壓縮算法系列 
+ rand.c 用於產生隨機數 
+ release.c 用於發佈時使用 
+ sha1.c sha加密算法的實現 
+ util.c 通用工具方法 
+ crc64.c 循環冗餘校驗 
+ sort.c SORT命令的實現

一些封裝類的代碼實現: 
+ bio.c background I/O的意思,開啓後臺線程用的 
+ latency.c 延遲類 
+ migrate.c 命令遷移類,包括命令的還原遷移等 
+ pqsort.c 排序算法類 
+ rio.c redis定義的一個I/O類 
+ syncio.c 用於同步Socket和文件I/O操做

整個Redis的源碼分類大致上如上所述了,接下來就按照既定的幾個階段一一去分析Redis這款如此優秀的源代碼吧!

Ps: 又給本身制定了一個艱鉅的計劃,但願本身能像以前同樣堅持下去,一點一點去剖析,相信最後會收穫不少!

相關文章
相關標籤/搜索