如何阅读 Redis 源码?ZZ
原文链接
在这篇文章中, 我将向大家介绍一种我认为比较合理的 Redis 源码阅读顺序, 希望可以给对 Redis 有兴趣并打算阅读 Redis 源码的朋友带来一点帮助。
第 1 步:阅读数据结构实现
刚开始阅读 Redis 源码的时候, 最好从数据结构的相关文件开始读起, 因为这些文件和 Redis 中的其他部分耦合最少, 并且这些文件所实现的数据结构在大部分算法书上都可以了解到, 所以从这些文件开始读是最轻松的、难度也是最低的。
下表列出了 Redis 源码中, 各个数据结构的实现文件:
文件 | 内容 |
---|---|
sds.h 和 sds.c |
Redis 的动态字符串实现。 |
adlist.h 和 adlist.c |
Redis 的双端链表实现。 |
dict.h 和 dict.c |
Redis 的字典实现。 |
redis.h 中的 zskiplist 结构和 zskiplistNode 结构, 以及 t_zset.c 中所有以 zsl 开头的函数, 比如 zslCreate 、 zslInsert 、 zslDeleteNode ,等等。 |
Redis 的跳跃表实现。 |
hyperloglog.c 中的 hllhdr 结构, 以及所有以 hll 开头的函数。 |
Redis 的 HyperLogLog 实现。 |
第 2 步:阅读内存编码数据结构实现
在阅读完和数据结构有关的文件之后, 接下来就应该阅读内存编码(encoding)数据结构了。
和普通的数据结构一样, 内存编码数据结构基本上是独立的, 不和其他模块耦合, 但是区别在于:
- 上一步要读的数据结构, 比如双端链表、字典、HyperLogLog, 在算法书上或者相关的论文上都可以找到资料介绍。
- 而内存编码数据结构却不容易找到相关的资料, 因为这些数据结构都是 Redis 为了节约内存而专门开发出来的, 换句话说, 这些数据结构都是特制(adhoc)的, 除了 Redis 源码中的文档之外, 基本上找不到其他资料来了解这些特制的数据结构。
不过话又说回来, 虽然内存编码数据结构是 Redis 特制的, 但它们基本都和内存分配、指针操作、位操作这些底层的东西有关, 读者只要认真阅读源码中的文档, 并在有需要时, 画图来分析这些数据结构, 那么要完全理解这些内存编码数据结构的运作原理并不难, 当然这需要花一些功夫。
下表展示了 Redis 源码中, 各个内存编码数据结构的实现文件:
文件 | 内容 |
---|---|
intset.h 和 intset.c |
整数集合(intset)数据结构。 |
ziplist.h 和 ziplist.c |
压缩列表(zip list)数据结构。 |
第 3 步:阅读数据类型实现
在完成以上两个阅读步骤之后, 我们就读完了 Redis 六种不同类型的键(字符串、散列、列表、集合、有序集合、HyperLogLog)的所有底层实现结构了。
接下来, 为了知道 Redis 是如何通过以上提到的数据结构来实现不同类型的键, 我们需要阅读实现各个数据类型的文件, 以及 Redis 的对象系统文件, 这些文件包括:
文件 | 内容 |
---|---|
object.c |
Redis 的对象(类型)系统实现。 |
t_string.c |
字符串键的实现。 |
t_list.c |
列表键的实现。 |
t_hash.c |
散列键的实现。 |
t_set.c |
集合键的实现。 |
t_zset.c 中除 zsl 开头的函数之外的所有函数。 |
有序集合键的实现。 |
hyperloglog.c 中所有以 pf 开头的函数。 |
HyperLogLog 键的实现。 |
第 4 步:阅读数据库实现相关代码
在读完了 Redis 使用所有底层数据结构, 以及 Redis 是如何使用这些数据结构来实现不同类型的键之后, 我们就可以开始阅读 Redis 里面和数据库有关的代码了, 它们分别是:
文件 | 内容 |
---|---|
redis.h 文件中的 redisDb 结构, 以及 db.c 文件。 |
Redis 的数据库实现。 |
notify.c |
Redis 的数据库通知功能实现代码。 |
rdb.h 和 rdb.c |
Redis 的 RDB 持久化实现代码。 |
aof.c |
Redis 的 AOF 持久化实现代码。 |
选读
Redis 有一些独立的功能模块, 这些模块可以在完成第 4 步之后阅读, 它们包括:
文件 | 内容 |
---|---|
redis.h 文件的 pubsubPattern 结构,以及 pubsub.c 文件。 |
发布与订阅功能的实现。 |
redis.h 文件的 multiState 结构以及 multiCmd 结构, multi.c 文件。 |
事务功能的实现。 |
sort.c |
SORT 命令的实现。 |
bitops.c |
GETBIT 、 SETBIT 等二进制位操作命令的实现。 |
第 5 步:阅读客户端和服务器的相关代码
在阅读完数据库实现代码, 以及 RDB 和 AOF 两种持久化的代码之后, 我们可以开始阅读客户端和 Redis 服务器本身的实现代码, 和这些代码有关的文件是:
文件 | 内容 |
---|---|
ae.c ,以及任意一个 ae_*.c 文件(取决于你所使用的多路复用库)。 |
Redis 的事件处理器实现(基于 Reactor 模式)。 |
networking.c |
Redis 的网络连接库,负责发送命令回复和接受命令请求, 同时也负责创建/销毁客户端, 以及通信协议分析等工作。 |
redis.h 和 redis.c 中和单机 Redis 服务器有关的部分。 |
单机 Redis 服务器的实现。 |
如果读者能完成以上 5 个阅读步骤的话, 那么恭喜你, 你已经了解了单机的 Redis 服务器是怎样处理命令请求和返回命令回复, 以及是 Redis 怎样操作数据库的了, 这是 Redis 最重要的部分, 也是之后继续阅读多机功能的基础。
选读
Redis 有一些独立的功能模块, 这些模块可以在完成第 5 步之后阅读, 它们包括:
文件 | 内容 |
---|---|
scripting.c |
Lua 脚本功能的实现。 |
slowlog.c |
慢查询功能的实现。 |
monitor.c |
监视器功能的实现。 |
第 6 步:阅读多机功能的实现
在弄懂了 Redis 的单机服务器是怎样运作的之后, 就可以开始阅读 Redis 多机功能的实现代码了, 和这些功能有关的文件为:
文件 | 内容 |
---|---|
replication.c |
复制功能的实现代码。 |
sentinel.c |
Redis Sentinel 的实现代码。 |
cluster.c |
Redis 集群的实现代码。 |
注意, 因为 Redis Sentinel 用到了复制功能的代码, 而集群又用到了复制和 Redis Sentinel 的代码, 所以在阅读这三个模块的时候, 记得先阅读复制模块, 然后阅读 Sentinel 模块, 最后才阅读集群模块, 这样理解起来就会更得心应手。
如果你连这三个模块都读完了的话, 那么恭喜你, 你已经读完了 Redis 单机功能和多机功能的所有代码了!
下图总结了本文介绍的阅读顺序:
结语
Redis 的设计非常简洁、优美、精巧和高效, 任何人只要愿意去阅读它的代码的话, 应该都会有所收获的。
希望这篇文章能够给想要阅读 Redis 代码的朋友们带来一些帮助, 也欢迎各位随时和我讨论 Redis 源码方面的问题, 或者跟我分享各位阅读 Redis 源码的心得和经验。
另外我的 Redis 源码注释 项目以及 《Redis 设计与实现》 一书对于理解 Redis 的源代码应该也会有所帮助, 有兴趣的朋友可以自行了解该项目/书本。
http://blog.huangz.me/diary/2014/how-to-read-redis-source-code.html
如何阅读 Redis 源码?ZZ的更多相关文章
- Redis源码阅读(一)事件机制
Redis源码阅读(一)事件机制 Redis作为一款NoSQL非关系内存数据库,具有很高的读写性能,且原生支持的数据类型丰富,被广泛的作为缓存.分布式数据库.消息队列等应用.此外Redis还有许多高可 ...
- Redis源码分析系列
0.前言 Redis目前热门NoSQL内存数据库,代码量不是很大,本系列是本人阅读Redis源码时记录的笔记,由于时间仓促和水平有限,文中难免会有错误之处,欢迎读者指出,共同学习进步,本文使用的Red ...
- Redis源码剖析--源码结构解析
请持续关注我的个人博客:https://zcheng.ren 找工作那会儿,看了黄建宏老师的<Redis设计与实现>,对redis的部分实现有了一个简明的认识.在面试过程中,redis确实 ...
- 曹工说Redis源码(3)-- redis server 启动过程完整解析(中)
文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...
- 柔性数组(Redis源码学习)
柔性数组(Redis源码学习) 1. 问题背景 在阅读Redis源码中的字符串有如下结构,在sizeof(struct sdshdr)得到结果为8,在后续内存申请和计算中也用到.其实在工作中有遇到过这 ...
- [Redis源码阅读]sds字符串实现
初衷 从开始工作就开始使用Redis,也有一段时间了,但都只是停留在使用阶段,没有往更深的角度探索,每次想读源码都止步在阅读书籍上,因为看完书很快又忘了,这次逼自己先读代码.因为个人觉得写作需要阅读文 ...
- Redis源码阅读(二)高可用设计——复制
Redis源码阅读(二)高可用设计-复制 复制的概念:Redis的复制简单理解就是一个Redis服务器从另一台Redis服务器复制所有的Redis数据库数据,能保持两台Redis服务器的数据库数据一致 ...
- Redis源码阅读(六)集群-故障迁移(下)
Redis源码阅读(六)集群-故障迁移(下) 最近私人的事情比较多,没有抽出时间来整理博客.书接上文,上一篇里总结了Redis故障迁移的几个关键点,以及Redis中故障检测的实现.本篇主要介绍集群检测 ...
- Redis源码阅读(五)集群-故障迁移(上)
Redis源码阅读(五)集群-故障迁移(上) 故障迁移是集群非常重要的功能:直白的说就是在集群中部分节点失效时,能将失效节点负责的键值对迁移到其他节点上,从而保证整个集群系统在部分节点失效后没有丢失数 ...
随机推荐
- 高版本sonar安装遇到的坑-sonar 6.7.5
最近安装了6.7.5版本的sonar,发现里面的坑还是很多,下面列举下遇到的坑 sonar插件地址:https://docs.sonarqube.org/display/PLUG/Plugin+Lib ...
- (转)使用LVS实现负载均衡原理及安装配置详解
使用LVS实现负载均衡原理及安装配置详解 原文:https://www.cnblogs.com/liwei0526vip/p/6370103.html
- selenium+JDBC实现参数自动化测试
测试模拟环境:在www.1905.com网站中执行两个用户的登陆退出操作 需要的文件有: 1.User的实例类: public class User { private String username ...
- android viewpager 拿到当前显示的 fragment 的实例
一个 ViewPager 通过 FragmentPagerAdapter 绑定了 3 个 fragment 可以通过 Fragment fragment = getSupportFragmentMan ...
- C 标准库 - string.h
C 标准库 - string.h This header file defines several functions to manipulate C strings and arrays. stri ...
- android studio Cannot resolve symbol '@drawable/XXX'等问题解决办法
方法1."Build " -> "Clean project" 方法 2."Tools" -> "Android&qu ...
- 九度oj 1006 ZOJ问题 2010年浙江大学计算机及软件工程研究生机试真题
题目1006:ZOJ问题 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:16244 解决:2742 题目描述: 对给定的字符串(只包含'z','o','j'三种字符),判断他是否能AC.是 ...
- TCP/IP协议簇分层详解---转
http://blog.csdn.net/hankscpp/article/details/8611229 一. TCP/IP 和 ISO/OSI ISO/OSI模型,即开放式通信系统互联参考模型(O ...
- Java中final修饰参数的作用
在方法参数前面加final关键字就是为了防止数据在方法体中被修改. 主要分两种情况:第一,用final修饰基本数据类型:第二,用final修饰引用类型. 第一种情况,修饰基本类型(非引用类型).这时参 ...
- java爬取百度首页源代码
爬虫感觉挺有意思的,写一个最简单的抓取百度首页html代码的程序.虽然简单了一点,后期会加深的. package test; import java.io.BufferedReader; import ...