要从零开始学习Redis内部实现,首先克隆Redis仓库:git clone https://github.com/redis/redis.git。然后从src目录下的redis.c文件入手,这是程序的主入口,理解main函数如何初始化服务器、监听端口、处理事件循环。接着阅读ae.c了解事件引擎,这是Redis单线程模型的核心,使用epoll/kqueue/select处理IO事件。数据结构从src/anet.c网络库开始,逐步深入到t_string.c、t_hash.c等对象实现。建议用gdb调试,设置断点在acceptTcpHandler函数,观察客户端连接处理流程。阅读源码时关注server.c中的serverCron定时任务,它负责内存回收、过期键删除等维护工作。通过这些步骤逐步掌握Redis的内存管理、命令执行、多路复用等机制。
第一步:准备环境
安装gcc、make、tcl等依赖。下载Redis源码后,不要直接make,会跳过很多细节。用make distclean清理后,逐文件阅读。推荐工具:vscode + Redis源码插件,或CLion配置远程调试。打印函数如llabs改为printf观察变量变化。
从main函数开始
redis.c的main函数调用initServerConfig初始化配置,setupSignalHandlers设置信号处理,initServer加载模块,aeMain启动事件循环。这是整个服务器启动流程。理解这里就能知道Redis如何从配置到运行。
事件循环aeMain
ae.c实现了事件抽象层,Redis用文件事件(读写)和时间事件。processEvents函数不断调用aeApiPoll等待事件,fireDoc事件处理命令。单线程非阻塞的关键在这里。
数据结构sdshdr
sds.c定义简单动态字符串,比C字符串高效,支持二进制安全。Redis所有key、value底层用sds。阅读sdsNewlen、sdscatlen等函数,理解预分配、收缩策略,避免内存碎片。
字典hashtable
dict.c是Redis哈希表,支持渐进式rehash。渐进rehash在serverCron中分批进行,避免阻塞。db.c的dict是数据库,每个db有dict存键值对。
对象系统robj
每个键值对是robj对象,type字段指明string、list等,encoding指定内部编码如ziplist、skiplist。lookupKeyRead查找键,dbAdd插入。编码转换如string对象用embstr小字符串优化。
命令执行processCommand
客户端socket读命令到querybuf,解析成argv/argc,调用c->cmd->proc,如setCommand。命令注册在redisCommandTable,每个命令有arity、flags。
内存管理zmalloc
zmalloc封装malloc,支持jemalloc。server.maxmemory配置内存上限,eviction处理内存不足,如allkeys-lru。lazyfree异步释放大对象。
FAQ
Q: 如何调试Redis源码?
A: 用gdb --args ./redis-server,break processCommand,run,观察调用栈。
Q: Redis单线程为什么这么快?
A: 事件驱动、非阻塞IO、数据结构优化、CPU缓存友好。
Q: 从哪里开始读源码最合适?
A: redis.c main函数,然后ae.c事件循环,再db.c数据库。
Q: 模块系统在哪里实现?
A: module.c,Redis 4.0引入,用moduleRegisterCommand注册命令。