定制网站和模板网站有何区别,图文广告开店培训班,中国设计师协会,网站字体大小是多少作者|Magic Kaito来源|水滴与银弹阅读本文大约需要 8 分钟。你好#xff0c;我是 Kaito。用了这么久的 Redis#xff0c;也翻了很多次源码#xff0c;经常有人问我到底怎么读 Redis 源码。一提到读源码#xff0c;很多人都会比较畏惧#xff0c;认为读源码是高手才会做的事… 作者|Magic Kaito来源|水滴与银弹阅读本文大约需要 8 分钟。你好我是 Kaito。用了这么久的 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 的底层是 SDSList 的底层是 ziplist quicklistHash 底层可能是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、注册读事件、读客户端 socketnetworking.c。处理具体的命令找到对应的命令函数、执行命令server.c、t_string.c、t_list.c、t_hash.c、t_set.c、t_zset.c。返回响应给客户端写客户端缓冲区、注册写事件、写客户端 socketnetworking.c。沿着这条主线去读代码我们就可以掌握一条命令的执行全过程。而且由于这条主线的代码逻辑已经覆盖了「所有命令」的执行流程我们下次再去读其它命令时比如 SADD就只需要关注「处理命令」部分的逻辑即可其它逻辑有 80% 都是相同的。05 先整体后细节当然在阅读主线代码的过程中肯定也会遇到过于「复杂」的函数第一次在读这种函数时很容易就会「陷进去」导致整个主线代码的阅读无法继续推进下去。遇到这种情况其实是很正常的可这时我们应该怎么办呢这里我的做法是前期读到这种逻辑时不要马上陷入到细节中去而是要先「抓整体」。具体来说对于复杂的函数逻辑我们刚开始并不需要知道它的每一个细节是如何实现的而是只需知道这个函数「大致」做了几件事情即可。举个例子在执行 HSET 命令时有一段代码很复杂其中包括了很多分支判断一次很难读懂那么我在读这段代码时就可以先简化逻辑把握整体思路之后再了解每个分支大致做了哪些事情这样做的好处一是不会被复杂的细节逻辑搞晕打击自己的自信心二是可以有效避免阅读的连贯性被打断从而能持续推进我们把整个主线逻辑读完。所以这里的重点就是先把复杂代码的主逻辑搞清楚知道涉及的每个方法完成了什么事心里要先搭建一个简单的「框架」等有了框架之后我们再去给框架填充「细节」。这样通过「先整体后细节」的方式我们就可以不再畏惧代码中的复杂逻辑。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、查漏补缺在工作中遇到具体问题带着这些实际的问题出发再次去读源码进行查漏补缺填补之前读源码时没有注意到的地方。往期推荐“5GAI”到底有啥用云原生时代底层性能如何调优到底什么是“无源物联网”张一鸣购得元宇宙入场券谁将是头号玩家点分享点收藏点点赞点在看