我看的源码是redis5.0的,可以自行到github上下载:GitHub - redis/redis at 5.0。部分代码看的redis6.0。
redis5.0源码的目录结构:
deps目录:
该包下是四种第三方依赖库。它主要存放了三类代码:① Redis 依赖的、实现更加高效的功能库,如内存分配;②独立于 Redis 开发演进的代码,如客户端;③ lua 脚本代码。后续完成功能的设计实现时,就可以在 deps 目录找到它们。
src目录:
这个目录里面包含了 Redis 所有功能模块的代码文件,也是 Redis 源码的重要组成部分。
tests目录:
在软件产品的开发过程中,除了第三方依赖库和功能模块源码以外,我们通常还需要在系统源码中,添加用于功能模块测试和单元测试的代码。而在 Redis 的代码目录中,就将这部分代码用一个 tests 目录统一管理了起来。
Redis 实现的测试代码可以分成四部分,分别是单元测试(对应 unit 子目录),Redis Cluster 功能测试(对应 cluster 子目录)、哨兵功能测试(对应 sentinel 子目录)、主从复制功能测试(对应 integration 子目录)。这些子目录中的测试代码使用了 Tcl 语言(通用的脚本语言)进行编写,主要目的就是方便进行测试。
不过在 tests 目录中,除了有针对特定功能模块的测试代码外,还有一些代码是用来支撑测试功能的,这些代码在 assets、helpers、modules、support 四个目录中。
utils目录:
在 Redis 开发过程中,还有一些功能属于辅助性功能,包括用于创建 Redis Cluster 的脚本、用于测试 LRU 算法效果的程序,以及可视化 rehash 过程的程序。在 Redis 代码结构中,这些功能代码都被归类到了 utils 目录中统一管理。
简单介绍:
数据类型:
- String(t_string.c、sds.c、bitops.c)
- List(t_list.c、ziplist.c、quicklist.c)
- Hash(t_hash.c、ziplist.c、dict.c、listpack.c)
- Set(t_set.c、intset.c)
- Sorted Set(t_zset.c、ziplist.c、dict.c)
- HyperLogLog(hyperloglog.c)
- Geo(geo.c、geohash.c、geohash_helper.c)
- Stream(t_stream.c、rax.c、listpack.c)
全局:
- Server(server.c、anet.c)
- Object(object.c)
- 键值对(db.c)
- 事件驱动(ae.c、ae_epoll.c、ae_kqueue.c、ae_evport.c、ae_select.c、networking.c)
- 内存分配(zmalloc.h,zmalloc.c)
- 内存回收(expire.c、lazyfree.c)
- 内存驱逐(lru、lfu等操作)(evict.c)
- 后台线程(bio.c)
- 事务(multi.c)
- PubSub(pubsub.c)
- 双向链表(adlist.c)
高可用&集群:
- 持久化:RDB(rdb.c、redis-check-rdb.c)、AOF(aof.c、redis-check-aof.c)
- 主从复制(replication.c)
- 哨兵(sentinel.c)
- 集群(cluster.c)
辅助功能:
- 延迟统计(latency.c)
- 慢日志(slowlog.c)
- 通知(notify.c)
- 基准性能(redis-benchmark.c)
上诉源代码大部分都值得一读!!!
服务器基础定义、初始化:
服务器事件驱动模型和网络通信相关:
ae.h:包含了服务器事件机制的一些结构体,比如:aeEventLoop、aeFileEvent、aeTimeEvent、aeFiredEvent。
ae.c:主要是服务器事件机制的一些运行代码,aeMain是最核心的部分,整个服务器都是在这个函数中一直循环;每一次循环调用aeProcessEvents进行处理事件;processTimeEvents主要用于定时任务的处理;其他的诸如:aeCreateEventLoop、aeDeleteEventLoop、aeCreateFileEvent、aeDeleteFileEvent、aeCreateTimeEvent、aeDeleteTimeEvent都是一些核心函数。
ae_epoll.c、ae_evport.c、ae_kqueue.c、ae_select.c:这是四种网络通信框架,都包含aeApiPoll函数,主要是用于对套接字的监听。
anet.h、anet.c:redis对网络通信(socket)的简单封装和一些状态设置的封装。状态设置主要包括socket连接的阻塞性、tcp的保活定时器的设置、设置发送缓冲区、tcp的Nagle算法设置、设置发送超时时间、地址重用的设置等。
networking.c:这是一个很核心的源文件,主要包括建立/清除和客户端的链接、接收/传送/处理客户端数据、跟客户端相关的事件处理器等。比如:createClient、resetClient等客户端操作,acceptTcpHandler、acceptUnixHandler处理客户端连接,readQueryFromClient命令请求处理器,sendReplyToclient命令回复处理器,addReply处理返回数据,prepareClientToWrite判断是否需要返回数据,writeToClient写数据给客户端,processInlineBuffer处理inline协议的数据,processMultibulkBuffer处理multibulk协议的数据,processInputBuffer处理输入的数据,processInputBufferAndReplicate处理输入的数据并进行复制等等。
在redis6.0中,还引入了多IO线程操作:initThreadedIO初始化多个IO线程、IOThreadMain为各个IO线程处理客户端读/写操作、stopThreadedIOIfNeeded有条件关闭IO线程、startThreadedIO开启IO线程、stopThreadedIO关闭IO线程、postponeClientRead判断能否推迟从客户端读取数据、clientInstallWriteHandler判断能否推迟向客户端写数据、handleClientsWithPendingReadsUsingThreads将 clients_pending_read 列表中的客户端分配给 IO 线程进行处理、handleClientsWithPendingWritesUsingThreads将 clients_pending_write 列表中的客户端分配给 IO 线程进行处理。
数据库数据类型和操作:
Redis 数据库提供了丰富的键值对类型,其中包括了 String、List、Hash、Set 和 Sorted Set 这五种基本键值类型。此外,Redis 还支持位图、HyperLogLog、Geo 等扩展数据类型。
而为了支持这些数据类型,Redis 就使用了多种数据结构来作为这些类型的底层结构。比如,String 类型的底层数据结构是 SDS,而 Hash 类型的底层数据结构包括哈希表和压缩列表。
除了图上的,还有quicklist、listpack、rax等。
除了实现了诸多的数据类型以外:
持久化相关:
内存驱逐:
后台线程:
集群、sentinel相关的太复杂,就不做简述了,可以去具体章节看。
以上就是在我学习redis源码中,涉及到的主要源码文件,有些太复杂或没有涉及的就没有罗列了,后续继续学习会继续增加。
更多源码可以参考前面每一章节的源码解析,也可以参考如下: