如何阅读 Redis 源码?

首先阅读数据结构,和其他部分耦合最少,实现 redis 的基础, 数据结构算法书上都可了解到, 读最轻松、难度最低

  • 自底向上:从耦合关系最小的模块开始读,然后逐渐过度到关系紧密的模块。好像写程序的测试一样,先从单元测试开始,然后才到功能测试

    先从单独的数据结构模块开始,然后再过渡到高层的功能模块

  • 从功能入手:通过文件名(模块名)和函数名,快速定位到一个功能的具体实现,然后追踪整个实现的运作流程,从而了解该功能的实现方式

  • 自顶向下:从程序的 main() 函数,或者某个特别大的调用者函数为入口,以深度优先或者广度优先的方式阅读它的源码

block-beta

   columns 1

   数据结构\nsds、adlist、t_zset、hyperloglog

   内存编码\nziplist、intset

   数据类型\nobject、t_string、t_list、t_set、t_zset

   数据库相关\ndb、notify、rdb、aof

   客户端与服务器相关\nae、networking、rediscli

   多机功能\nreplication、sentinel、cluster

数据结构实现

文件 内容
sds.h、sds.c 动态字符串
adlist.h、adlist.c 双端链表
dict.h、dict.c 字典
redis.h zskiplist 和 zskiplistNode 结构, t_zset.c zsl 开头的函数,如 zslCreate 、 zslInsert 、 zslDeleteNode 等 跳跃表
hyperloglog.c 中 hllhdr 结构, hll 开头的函数 HyperLogLog

内存编码数据结构

Redis 为了节约内存而专门开发,数据结构都是特制(adhoc)的

基本都和内存分配、指针操作、位操作这些底层的东西有关

文件 内容
intset.h 和 intset.c 整数集合(intset)
ziplist.h 和 ziplist.c 压缩列表(zip list)

数据类型实现

文件 内容
object.c 对象(类型)系统实现
t_string.c 字符串键
t_list.c 列表键
t_hash.c 散列键
t_set.c 集合键
t_zset.c 中除 zsl 开头的函数之外的所有函数 有序集合键
hyperloglog.c 中所有以 pf 开头的函数 HyperLogLog 键

数据库实现

文件 内容
redis.h 中 redisDb 结构, db.c 数据库实现
notify.c 数据库通知功能
rdb.h 和 rdb.c RDB 持久化
aof.c AOF 持久化

其他

文件 内容
redis.h 的 pubsubPattern 结构,pubsub.c 文件。 发布与订阅
redis.h 的 multiState 及 multiCmd 结构, multi.c 事务
sort.c SORT
bitops.c GETBIT 、 SETBIT 等二进制位操作

客户端和服务器

文件 内容
ae.c ,及ae_*.c (多路复用库) 事件处理器实现(基于 Reactor 模式)
networking.c 网络连接库,负责发送命令回复和接受命令请求, 同时也负责创建/销毁客户端, 以及通信协议分析等工作
redis.h 和 redis.c 中和单机 Redis 服务器有关的部分 单机 Redis 服务器的实现
文件 内容
scripting.c Lua
slowlog.c 慢查询
monitor.c 监视器

多机功能

文件 内容
replication.c 复制功能
sentinel.c Sentinel
cluster.c 集群的实现

Sentinel 用到复制功能, 而集群又用到了复制和 Sentinel,先阅读复制模块, 然后Sentinel 模块, 最后才阅读集群模块

运行调试

win 11 装好 wsl, git gcc cmake gdb后

在wsl 里 git clone https://github.com/redis/redis.git --depth=1

clion 已支持 Makefile 项目直接导入

makefile 默认用 -O3,调试启动时断点会不正确

make CFLAGS="-O0" -j$(nproc)

重新编译一下即可正常断点