色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

我們怎樣讀源碼才能更高效

數據分析與開發 ? 來源:水滴與銀彈 ? 作者:Magic Kaito ? 2021-11-12 09:38 ? 次閱讀

用了這么久的 Redis,也翻了很多次源碼,經常有人問我到底怎么讀 Redis 源碼。

一提到讀源碼,很多人都會比較畏懼,認為讀源碼是高手才會做的事情。他們可能遇到問題時,會更傾向于去找別人分享的答案。但往往很多時候,自己查到的資料并不能解決所有問題,尤其是比較細節的問題。

從我的實戰經驗來看,遇到這種情況,通常就需要去源碼中尋找答案了,因為在源碼面前,這些細節會變得「一覽無余」。

而且我認為,掌握讀源碼的能力,是從只懂得如何使用 Redis,到精通 Redis 實現原理的成長之路上,必須跨越的門檻。

可是,面對龐大復雜的項目,我們怎樣讀源碼才能更高效呢?

這篇文章我就來和你聊一聊,我讀 Redis 源碼的經驗,以及讀源碼的「通用思路」,希望這些心得可以幫助到你。

01 找到地圖

很多開源項目的源碼,代碼量一般都比較龐大,如果在讀代碼之前,我們沒有制定合理的方法,就一頭扎進去讀代碼,勢必會把自己搞暈。

所以,我在拿到一個項目的代碼之后,并不會馬上著手去讀,而是會先對整個項目結構進行梳理,劃分出項目具體包含的模塊。這樣,我就對整個項目有了一個「宏觀」的了解。

讀代碼就好比去一個陌生城市旅行,這個旅途過程充滿著未知。如果在出發之前,我們手里能有一張地圖,那我們對自己的行程就可以有一個非常清晰的規劃。

我們就知道,如果想要到達目的地,需要從哪里出發、經過哪些地方、通過什么方式才能到達,有了地圖就有了行進方向,否則很容易迷失。

因此,提前花一些時間梳理整個項目的「結構和目錄」,對于后面更好地閱讀代碼是非常有必要的。

就拿 Redis 來舉例,在讀 Redis 源碼之前,我們可以先梳理出整個項目的功能模塊,以及每個模塊對應的代碼文件(src 下的代碼結構):

這樣,有了這張地圖之后,我們再去看代碼的時候,就可以有重點地閱讀了。

02 前置知識準備

在梳理完整個項目結構之后,我們就可以正式進入閱讀環節當中了。不過,在閱讀代碼之前,我們其實還需要預先掌握一些「前置知識」。

因為一個完整的項目,必然綜合了各個領域的技術知識點,比如數據結構、操作系統網絡協議、編程語言等,如果我們提前做好一些功課,在讀源碼的過程中就會輕松很多。

以下是根據我在閱讀 Redis 書籍和實戰過程中,提取的讀源碼必備前置知識點,你可以參考下:

常用數據結構:數組、鏈表、哈希表、跳表

網絡協議:TCP 協議

網絡 IO 模型:IO 多路復用、非阻塞 IO、Reactor 網絡模型

操作系統:寫時復制(Copy On Write)、常見系統調用、磁盤 IO 機制

C 語言基礎:循環、分支、結構體、指針

當然,在閱讀源碼的過程中,我們也可以根據實際問題再去查閱相關資料,但不管怎樣,提前熟悉這些方面的知識,在真正讀代碼時就會省下不少時間。

03 從基礎模塊開始讀

好,有了地圖并掌握了前置知識之后,接下來我們就要進入主題了:讀代碼。

但具體要從哪個地方開始讀起呢?我認為要先從「最基礎」的模塊開始讀起。

我在前面也分析了,一個完整的項目會劃分很多的功能模塊,但這些模塊并不是孤立的,而很可能是有「依賴」關系的。

比如說,Redis 中的 networking.c 文件,表示處理網絡 IO 的具體實現。而如果我們能在理解事件驅動模塊 ae.c 的基礎上,再去閱讀網絡 IO 模塊,效率就會更高。

那在 Redis 源碼中,哪些是最基礎的模塊呢?

想一下,我們在使用 Redis 時,接觸最頻繁的是哪些功能?

答案是各種數據類型。

一切操作的基礎,其實都是基于這些最常用的數據類型來做的,比如 String、List、Hash、Set、Sorted Set等。所以,我們就可以從這些基礎模塊開始讀起,也就是從 t_string.c、t_list.c、t_hash.c、t_set.c、t_zset.c 代碼入手。

如果你對 Redis 的數據類型有所了解,就會看到這些數據類型在實現時,底層都對應了不同的數據結構。比如,String 的底層是 SDS,List 的底層是 ziplist + quicklist,Hash 底層可能是ziplist,也可能是哈希表,等等。

由此一來,我們會發現,這些數據結構又是更為「底層」的模塊,所以我們在閱讀數據類型模塊時,就需要重點聚焦在這些模塊上,也就是 sds.c、ziplist.c、quicklist.c、dict.c、intset.c 文件,而且這些文件都是比較獨立的,閱讀起來就可以更加集中。

這樣,當我們真正掌握了這些「底層數據結構」的實現后,就能更好地理解基于它們實現的各種「數據類型」了。

這些基礎模塊就相當于一座大廈的地基,地基打好了,才能做到高樓聳立。

04 找到核心主線

接著,掌握了數據結構模塊之后,這時我們的重點就需要放在「核心主線」上來了。

在這個階段,我們需要找到一個明確的目標,以這個目標為主線去讀代碼。因為讀源碼一個很常見的需求,就是為了了解這個項目最「核心功能」的實現細節,我們只有以此為目標,找到這條主線去讀代碼,才能達到最終目的。

那么在讀 Redis 源碼時,什么才是它的核心主線呢?這里我分享一個非常好用的技巧,就是根據「Redis 究竟是怎么處理客戶端發來的命令的?」 為主線來梳理。

舉個例子,當我們在執行 SET testkey testval EX 60 這樣一條命令時,就需要搞清楚 Redis 是怎么執行這條命令的。

也就是要明確,Redis 從收到客戶端請求,到把數據存到 Redis 中、設置過期時間,最后把響應結果返回給客戶端,整個過程的每一個環節,到底是如何處理的。

有了這條主線,我們就有了非常明確的目標,而且沿著這條主線去讀代碼,我們還可以很清晰地把多個模塊「串聯」起來。比如從前面的例子中,我們會看到一條命令的執行,主要包含了這樣幾個階段。

Redis Server 初始化:加載配置、監聽端口、注冊連接建立事件、啟動事件循環(server.c、anet.c)。

接收、解析客戶端請求:初始化 client、注冊讀事件、讀客戶端 socket(networking.c)。

處理具體的命令:找到對應的命令函數、執行命令(server.c、t_string.c、t_list.c、t_hash.c、t_set.c、t_zset.c)。

返回響應給客戶端:寫客戶端緩沖區、注冊寫事件、寫客戶端 socket(networking.c)。

沿著這條主線去讀代碼,我們就可以掌握一條命令的執行全過程。

而且,由于這條主線的代碼邏輯,已經覆蓋了「所有命令」的執行流程,我們下次再去讀其它命令時,比如 SADD,就只需要關注「處理命令」部分的邏輯即可,其它邏輯有 80% 都是相同的。

05 先整體后細節

當然,在閱讀主線代碼的過程中,肯定也會遇到過于「復雜」的函數,第一次在讀這種函數時,很容易就會「陷進去」,導致整個主線代碼的閱讀,無法繼續推進下去。

遇到這種情況其實是很正常的,可這時我們應該怎么辦呢?

這里我的做法是,前期讀到這種邏輯時,不要馬上陷入到細節中去,而是要先「抓整體」。

具體來說,對于復雜的函數邏輯,我們剛開始并不需要知道它的每一個細節是如何實現的,而是只需知道這個函數「大致」做了幾件事情即可。

舉個例子,在執行 HSET 命令時,有一段代碼很復雜,其中包括了很多分支判斷,一次很難讀懂:

960dd93a-427c-11ec-b939-dac502259ad0.png

那么,我在讀這段代碼時,就可以先簡化邏輯,把握整體思路:

96b2cf9e-427c-11ec-b939-dac502259ad0.png

之后,再了解每個分支大致做了哪些事情:

974ab2dc-427c-11ec-b939-dac502259ad0.png

這樣做的好處,一是不會被復雜的細節邏輯搞暈,打擊自己的自信心,二是可以有效避免閱讀的連貫性被打斷,從而能持續推進我們把整個主線邏輯讀完。

所以,這里的重點就是:先把復雜代碼的主邏輯搞清楚,知道涉及的每個方法完成了什么事,心里要先搭建一個簡單的「框架」,等有了框架之后,我們再去給框架填充「細節」。

這樣通過「先整體后細節」的方式,我們就可以不再畏懼代碼中的復雜邏輯。

06 先主線后支線

不過,在閱讀主線代碼的過程中,我們肯定還會遇到各種「支線」邏輯,比如數據過期、替換淘汰、持久化、主從復制等。

其實,在閱讀主線邏輯的時候,我們并不需要去重點關注這些支線,而當整個主線邏輯「清晰」起來之后,我們再去讀這些支線模塊,就會容易很多了。

這時,我們就可以從這些支線中,選取下一個「目標」,帶著這個目標去閱讀,比如說:

過期策略是怎么實現的?(expire.c、lazyfree.c)

淘汰策略是如何實現的?(evict.c)

持久化 RDB、AOF 是怎么做的?(rdb.c、aof.c)

主從復制是怎么做的?(replication.c)

哨兵如何完成故障自動切換?(sentinel.c)

分片邏輯如何實現?(cluster.c)

。..

有了新的支線目標后,我們依舊可以采用前面提到的「先整體后細節」的思路閱讀相關模塊,這樣下來,整個項目的每個模塊,就可以被「逐一擊破」了。

07 查漏補缺

最后,我們還需要「查漏補缺」。

按照前面提到的方法,基本就可以把整個項目的主要模塊讀得七七八八了,這時我們基本已經對整個項目有了整體的「把控」。

不過,當我們在工作中遇到問題時,很有可能會發現,在當時讀代碼的過程中,有很多并不在意的「細節」被忽略了。

所以這時,我們就可以再帶著「具體問題」出發,聚焦這個問題相關的模塊,再一次去讀源碼。這樣一來,我們就可以填補當時閱讀源碼的「空白區」。

舉個例子,當我們在閱讀 String 底層數據結構 SDS(簡單動態字符串)的實現時,我們會看到當 SDS 需要追加新內容時會進行擴容,而我們之前閱讀這塊代碼時,很有可能只是了解到有這樣的邏輯存在,但并沒有在意擴容的相關細節(一次擴容多大)。

所以,當我們在工作中遇到這個細節問題后,就可以把目光聚焦在 SDS 的擴容邏輯上(sds.c 的sdsMakeRoomFor函數),而此時我們會發現,當需要申請的新內存小于 1MB 時,Redis 就會翻倍申請內存,否則按 1MB 申請新內存。

采用這個方法進行查漏補缺,我們就可以對整個項目了解得更深入、更全面,真正把項目「吃透」。

總結

好了,以上就是我在閱讀 Redis 源碼時的經驗心得,總結一下這 7 個步驟。

1、找到地圖:拿到項目代碼后,提前梳理整個項目結構,知曉整個項目的模塊劃分,以及對應的代碼文件。

2、前置知識準備:提前掌握項目中用到的前置知識,比如數據結構、操作系統原理、網絡協議、網絡 IO 模型、編程語言語法等等。

3、從基礎模塊開始讀:從最底層的基礎模塊開始入手,先掌握了這些模塊,之后基于它們構建的模塊讀起來會更加高效。

4、找到核心主線:找到整個項目中最核心的主線邏輯,以此為目標,了解各模塊為了完成這個功能,是如何協作和組織的。

5、先整體后細節:對于復雜函數,不要上來就陷入細節,前期閱讀只需了解這個函數大致做了什么事情,建立框架,等搭建起框架之后,再去填充細節。

6、先主線后支線:整個主線邏輯清晰之后,再去延伸閱讀支線邏輯,因為支線邏輯肯定是服務主線邏輯的,讀完主線后再去讀這些支線,也會變得更簡單。

7、查漏補缺:在工作中遇到具體問題,帶著這些實際的問題出發再次去讀源碼,進行查漏補缺,填補之前讀源碼時沒有注意到的地方。

后記

你可以看到,這篇文章介紹的閱讀源碼的方法,其實并不局限于讀 Redis 代碼。

這 7 個步驟,可以算是一個的「通用思路」,我也經常用這個思路來讀其它項目的源碼,非常有用,你也可以試試。

另外,我認為很多人讀源碼覺得難,一是因為心理上自認為自己讀不懂,不敢邁步這一步,二是因為找不到合理的方法,在讀源碼時屢次受挫,最終知難而退。

我在讀源碼時也經歷過這些,這里再分享一下我的經驗。

1、永遠不要給自己設限:想想看,曾經以為很多自己做不到的事,在有壓力的情況下,是不是慢慢都做到了,而且發現做得還挺好?學習技術也是一樣,技術是死的,東西就那么多,一遍不行來兩遍,總有一次能搞懂,所以心態上一定不要先「否定」自己,凡事先邁一小步進去試試看,好的開始就是成功的一半。

2、找到對的學習方法:正所謂「學會學習,再學習」,科學高效的方法,能幫你事半功倍,這篇文章分享的方法論,就是屬于學習方法的范疇,你可以結合自己的實際情況試試看。

希望我的這些經驗和心得,對你有所啟發。

如果你也有自己的閱讀源碼的實踐經驗和方法,歡迎在留言區分享出來,我們一起交流,共同進步~

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 源碼
    +關注

    關注

    8

    文章

    639

    瀏覽量

    29185
  • Redis
    +關注

    關注

    0

    文章

    374

    瀏覽量

    10871

原文標題:讀懂 Redis 源碼,我總結了這 7 點心得

文章出處:【微信號:DBDevs,微信公眾號:數據分析與開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    在TLV320AIC3254中怎樣頻率值和幅度值?

    TLV320AIC3254中怎樣頻率值和 幅度值,是在那個寄存器去?如果它有這個功能,我就不用對音頻做FFT了,謝謝。
    發表于 11-07 06:15

    二維碼識設備有哪些類型

    隨著二維碼應用的日益普及,各類二維碼識設備也應運而生。這些設備不僅極大地方便了我們的日常生活,也為企業提供了更加高效便捷的服務。那么,你知道二維碼識設備都有哪些類型嗎?讓
    的頭像 發表于 11-05 16:10 ?172次閱讀
    二維碼識<b class='flag-5'>讀</b>設備有哪些類型

    通過簡單的電阻電容組合怎樣才能把25K方波變成正弦?

    通過簡單的電阻電容組合怎樣才能把25K方波變成正弦呢。加了濾波電路后方波的上升沿變緩了,可是下降沿基本沒有變化。怎樣才能把下降沿也變緩呢
    發表于 10-22 06:02

    智能升級,樓宇自控系統讓辦公更高效

    智能升級,樓宇自控系統讓辦公更高效 在快節奏的現代都市生活中,辦公效率成為了企業競爭力的關鍵因素之一。隨著科技的飛速發展,樓宇自控系統作為智能建筑的核心技術,正逐步滲透到我們的辦公環境中,以其獨特
    的頭像 發表于 09-19 14:12 ?254次閱讀

    GaN如何實現更高效、更緊湊的電源

    電子發燒友網站提供《GaN如何實現更高效、更緊湊的電源.pdf》資料免費下載
    發表于 09-12 10:00 ?0次下載
    GaN如何實現<b class='flag-5'>更高效</b>、更緊湊的電源

    我們需要怎樣的大模型?

    AI時代,我們需要怎樣的大模型?這個問題盡管我們無法給出一個確定的答案,但顯而易見的是,用戶的選擇正逐漸匯聚成一股趨勢。6月28日,在WAVESUMMIT深度學習開發者大會上,百度公布了文心一言
    的頭像 發表于 07-03 08:05 ?112次閱讀
    <b class='flag-5'>我們</b>需要<b class='flag-5'>怎樣</b>的大模型?

    如何使用PyTorch構建更高效的人工智能

    術界和工業界得到了廣泛應用。本文將深入探討如何使用PyTorch構建更高效的人工智能系統,從框架基礎、模型訓練、實戰應用等多個方面進行詳細解析。
    的頭像 發表于 07-02 13:12 ?374次閱讀

    固定碼器怎么選型 工業二維碼碼器推薦

    碼器選型是一項重要的決策過程,涉及到多個因素的考慮。在選擇碼器時,我們需要根據實際應用環境、使用方式、預算、需求以及與其他設備或系統的兼容性等方面進行綜合評估。本文將為您詳細解讀讀碼器選型
    的頭像 發表于 06-24 14:19 ?358次閱讀
    固定<b class='flag-5'>讀</b>碼器怎么選型 工業二維碼<b class='flag-5'>讀</b>碼器推薦

    怎樣才能選到合適的無線模塊?

    市面上無線模塊的類型多種多樣,如LoRa、藍牙、ZigBee、SPI、SoC等等,怎樣才能選擇到合適的無線模塊呢?為了確保所選模塊能滿足特定應用的需求并實現最佳性能,在選擇模塊時可以重點考慮以下幾個
    的頭像 發表于 05-31 08:21 ?794次閱讀
    <b class='flag-5'>怎樣才能</b>選到合適的無線模塊?

    深圳特信電子|車載車庫GPS信號探測器:讓停車管理更高效智能

    深圳特信電子|車載車庫GPS信號探測器:讓停車管理更高效智能
    的頭像 發表于 05-23 08:54 ?338次閱讀

    比車用級別更高,eVTOL到底需要怎樣的電機?

    根據國家戰略規劃及行業發展需求,積極探索新的應用領域,適時調整產品布局。” 由此不難看出,相較于新能源汽車,eVTOL對電機有更高的要求,那么需要達到怎樣的水平呢? ? 電機壽命和可靠性是關鍵 由于是全新的產品形態,因而電池、電控
    的頭像 發表于 05-15 00:17 ?8074次閱讀
    比車用級別<b class='flag-5'>更高</b>,eVTOL到底需要<b class='flag-5'>怎樣</b>的電機?

    搭載星火認知大模型的AI鼠標:一鍵呼出AI助手,辦公更高效

    搭載星火認知大模型的AI鼠標:一鍵呼出AI助手,辦公更高效 在這個AI時代,如果你想在激烈競爭的職場中不被淘汰,訊飛AI鼠標AM30就是你的不二選擇。 這款鼠標搭載了星火認知大模型AI,為你提供了
    的頭像 發表于 03-25 11:52 ?483次閱讀
    搭載星火認知大模型的AI鼠標:一鍵呼出AI助手,辦公<b class='flag-5'>更高效</b>

    工業固定式碼器快速高效掃碼,實現防重復防漏條碼指令觸發功能

    在流水線生產的作業環境中,很多情況下是需要對產品上的二維碼進行識別和儲存并檢出錯碼和重碼的,以確保生產數據的完整性和準確性。而這些工業固定式碼器可以很好地幫助客戶完成。因為工業碼器采用先進
    的頭像 發表于 03-18 14:13 ?464次閱讀
    工業固定式<b class='flag-5'>讀</b>碼器快速<b class='flag-5'>高效</b>掃碼,實現防重復防漏條碼指令觸發功能

    動引擎:如何提供更高效的電動汽車

    上漲? 我們正面臨著汽車架構領域千載難逢的行業范式轉變。如果制造商能夠更高效地設計和生產電動汽車,同時集中整合電子組件的占位面積,并且成本比當前的模式便宜,那么電動汽車市場將繼續上升。在本文中,我們將探討電動汽車行業在多個層面上
    發表于 01-26 13:57 ?469次閱讀

    怎樣才能使用范圍(0x8004-0xBFFC)進行I2C寫入呢?

    我們怎樣才能使用范圍(0x8004-0xBFFC)進行 I2C 寫入呢? 我們可以直接將寫入的數據復制到范圍 (0x8000-0xBFFC) 嗎?或者需要配置其他寄存器?
    發表于 01-23 08:13
    主站蜘蛛池模板: 成人伦理影院| 伊人久久综在合线亚洲| 午夜电影三级还珠格格| 乌克兰少妇大胆大BBW| 午夜阳光影院在线观看视频| 亚洲乱色视频在线观看| 在线视频一区二区三区在线播放| 97人妻碰视频在线观看| 白丝高中生被c爽哭| 国产精品人妻无码久久久蜜桃| 国产真实女人一级毛片| 看黄色片子| 日本国产黄色片| 亚洲高清国产拍精品动图| 在线精品国精品国产不卡| yellow片高清视频免费看| 国产精品一区二区欧美视频| 久久99影院| 人人啪日日观看在线| 亚洲国产成人精品青青草原100| 最近中文字幕2019免费版| 芭乐视频网页版在线观看| 国产一区二区内射最近更新| 狼人大香伊蕉国产WWW亚洲| 日本三级按摩推拿按摩| 亚洲乱码一区二区三区香蕉| 97在线超碰免费视频| 国产精品久久人妻拍拍水牛影视| 久久视频精品38在线播放| 日本精品久久久久中文字幕| 亚洲精品乱码久久久久久v| bdsm中国精品调教ch| 国产亚洲精品久久久久久久| 男人J放进女人屁股免费观看| 少妇性饥渴BBBBBBBBB| 中国女人hd| 国产精品人妻无码免费A片导航 | 亚洲国产高清福利视频| 99re在线播放| 韩国g奶空姐| 日韩经典欧美一区二区三区|