Redis 7.0 源碼調試環境搭建與源碼導讀技巧
天下武功,無堅不摧,唯快不破!我的名字叫 Redis,全稱是 Remote Dictionary Server。
有人說,組 CP,除了要了解她外,還要給機會讓她了解你。
那么,作為開發工程師的你,是否愿意認真閱讀此心法抓住機會來了解我,運用到你的系統中提升性能。
我遵守 BSD 協議,由意大利人 Salvatore Sanfilippo 使用 C 語言編寫的一個基于內存實現的鍵值型非關系(NoSQL)數據庫。
我是一個內存數據結構存儲、可作為數據庫、緩存、消息隊列、流處理引擎,速度快是我的特點。
根據官方數據,Redis 的 QPS 可以達到約 100000(每秒請求數)。
我提供了 String(字符串)、Hashes(散列表)、Lists(列表)、Sets(無序集合)、Sorted Sets(可根據范圍查詢的排序集合)、Bitmap(位圖)、HyperLogLog、Geospatial (地理空間)和 Stream(流)等數據結構。
數據結構的使用技法和實現原理是你核心筑基必經之路,好好修煉。
除此之外,我還具有主從復制、Lua 腳本、LRU 淘汰機制,事務和不同級別的磁盤持久化功能,并通過 Redis Sentinel(哨兵)和 Redis Cluster(Redis 集群)實現高可用,這部分內容,重中之重,高手必備。
我還支持一些原子操作,支持異步復制實現快速非阻塞同步和自動重連,另外需要注意的是,推薦你在 Lunix /Unix 系統上部署,官方并沒有在 Windows 系統上構建安裝包。
1.1.1 Redis 能干啥
程許媛:“Redis 你說了這么多?你能干啥?別王婆賣瓜,自賣自夸?!?/p>
緩存
這是我被使用的最多的場景,能極大提升應用程序的性能。當單個 MySQL 讀寫壓力比較大,場景是讀多寫少的時候,把熱點數據存儲在更快的存儲中,也就是 Redis。
讀取數據
- 先從緩存中讀取數據是否命中。
- 緩存未命中,則查詢數據庫獲取數據,并把數據寫到 Redis 中,讓后續讀取相同數據的請求命中緩存,最后把數據返回給調用者。
- 緩存命中,直接返回。
寫數據
至于修改數據,程序員想了很多方法去盡可能保證 Redis 與 MySQL 的數據一致性。
- 先寫 MySQL 數據,再刪除 Redis 緩存數據。
- 監聽 MySQL binlog 日志,修改 Redis 數據。
排行榜
使用 MySQL 等關系型數據庫,非常麻煩,性能也差,而直接使用 Redis SortedSet 輕松搞定。
消息隊列
簡單消息隊列,在一些不需要高可靠,但是數據量大會給 MySQL 帶來非常大壓力的場景,比如:到貨通知、未讀消息、郵件發送之列的。程序員可以使用 Lists 來實現一個隊列。
分布式鎖
Redisson 這個框架,就是使用 Redis 弄出了一套分布式鎖解決方案。
計數器
Redis 的命令都是原子性的,程序員可以輕松地利用 INCR,DECR命令來構建計數器系統。
還有很多場景,我會在后面章節詳細道來,學完之后,我相信你定能筑基鍛體,念頭通達,升職加薪。
千古無同局,葉底能否藏花,我們未來印證,愿此心法能讓你學有所成,你來,我等著。
1.1.2 源代碼編譯
經過上一篇的 Redis 簡介,我相信你一定想繼續了解 Redis。本章節會通過源代碼編譯來安裝 Redis 7.0.5,讓你在自己的機器上搭建一套可以 Debug 的 Redis 7.0.5 源碼環境。
這也是后續原理分析的基礎,推薦你部署在 macOS 或者 Linux 上搭建,如果你是 Windows 環境,那就搞一個虛擬機在上面裝一個 Linux 系統,再繼續搭建 Redis 環境。
程許媛:“我的電腦是 Mac OS 系統,你就用這個來演示吧?!?/p>
獲取源代碼
有兩種方式,第一種是從官網下載 Redis 源碼壓縮包,如圖 1-1 所示。
圖1-1
將壓縮包解壓得到一個文件夾。
第二種方式,通過 git clone 獲取源碼。
從 Github 上,使用 git clone https://github.com/redis/redis.git指令下載,下載完成后你會得到如下文件。
圖 1-2
進入 redis 目錄,使用 git checkout 切換到 7.0.5 這個 tag 。
編譯 Redis
在編譯之前,需要安裝一些環境依賴,Redis 是 C 語言編寫的,所以還需要 gcc 編譯器。
執行 gcc -v判斷是否安裝了編譯器。
圖 1-3
沒有安裝的話,使用如下指令安裝。
一切準備就緒,進入 redis 的源碼目錄,執行 make命令就可以了,你可以類比成 Java 中的 mvn 命令。
命令后邊的 “-O0” 參數表示告訴編譯器不要優化代碼,防止你在 Debug 的時候, IDE 里面的 Redis 源碼與實際運行的代碼對應不上。
MALLOC=jemalloc ,指定在 Mac OS 系統上 Redis 使用 jemalloc 內存分配器,Linux 默認使用該分配器,如果是 Linux 系統,無需指定該參數。
內存碎片自動清理功能只在 jemalloc 內存分配器生效,所以才加上這個參數指定內存分配器。
如果在 Linux 系統上用于生產環境,那么直接使用指令 make命令即可。
編譯成功,將會看到圖 1-4 中Hint: It's a good idea to run 'make test' ;),提示我們可以運行單元測試,這一步可以省略。
圖 1-4
啟動 Redis
編譯成功,進入 src 源碼目錄下,你會看到一個 redis-server 的可執行程序,使用如下指令啟動。
圖 1-5
代碼調試環境搭建
編譯好了,我們還差一個方便閱讀和調試源碼的工具。為了方便閱讀和 debug 源碼,極力推薦你使用 CLion 來閱讀和調試 Redis 源碼,我使用的是 CLion 2021.3 版本,它支持 Makefile 的項目。
安裝好以后,打開 CLion,點擊 open,選擇 Redis 源碼目錄即可。
圖 1-6
之后檢查下 Run Debug 是否出現這些選項,選擇編輯。
圖 1-7
選擇編輯 redis-server ,指定啟動配置文件 redis.conf的目錄,保存。
圖 1-8
在 server.c? 的main() 方法加斷點,Debug 啟動 redis -server,進行源碼 Debug。
圖 1-9
大功告成,接下來就可以在 Redis 的知識海洋里嗆水了。
目錄結構
在知識海洋嗆水之前,先來了解下 Redis 的目錄結構,從 Redis 整體目錄結構來對系統有個全局的認識,了解一個系統的主要組成,同時防止陷入細節或者無從下手。
deps
這個目錄主要包含 Redis 所依賴的第三方代碼庫。
- Jemalloc,內存分配器,默認情況下選擇該內存分配器來代替 Linux 系統的 libc-malloc,libc-malloc 性能不高,且碎片化嚴重。
- hiredis,這是官方 C 語言客戶端。
- linenoise 是一種讀線替換。它由 Redis 的 同一作者開發,但作為一個單獨的項目進行管理,并根據需要進行更新。
- lua,顧名思義,就是 lua 相關的功能。
- hdr_histogram,用于生成每個命令的延遲跟蹤直方圖。
src 目錄
這是 Redis 源碼的重要組成部分,里面有 commands? 和 modules 兩個子目錄,其余功能模塊的源碼都在 src 目錄下,這是最重要的目錄。
modules?目錄包含了實現Redis module?的示例代碼,commands里面都是 json 格式的文件,包含了每個指令的元信息。
tests 目錄
顧名思義,功能模塊測試和單元測試的代碼就在這里。
- cluster,Redis Cluster 功能測試。
- sentinel,哨兵集群功能測試。
- unit,單元測試。
- integration,主從復制功能測試。
剩下的 assets、helpers、modules、support 四個目錄中是用來支撐測試功能的。
utils 目錄
輔助性功能的腳本或者代碼,比如用于創建 Redis Cluster 的腳本,lru 算法效果展示代碼等。
除此之外,Redis 源碼目錄還有兩個重要的文件,redis.conf 和 sentinel.conf,分別用于配置 Redis 實例運行和哨兵配置。