乐趣区

关于redis:Redis源码剖析与实战-学习笔记-Day1-Redis源码整体概览

Redis 代码的整体架构,就相当于给 Redis 代码画了张全景图。
有了这张图,咱们再去学习 Redis 不同功能模块的设计与实现时,就能够从图上疾速查找和定位这些功能模块对应的代码文件。

庖丁解牛
代码的目录构造和作用划分 了解 Redis 代码的整体架构,以及所蕴含的代码性能类别;
零碎功能模块与对应代码文件 目标是理解 Redis 实例提供的各项性能及其相应的实现文件,以便后续深刻学习。

(1) Redis 目录构造

在学习一个大型系统软件的代码时,要想疾速地对代码有个初步认知,理解零碎源码的整体目录构造就是一个卓有成效的办法。

对于 Redis 来说,在它的源码总目录下,一共蕴含了 depssrctestsutils 四个子目录,这四个子目录别离对应了 Redis 中施展不同作用的代码,上面咱们具体来看看。

(1.1) deps 目录

这个目录次要蕴含了 Redis 依赖的第三方代码库,包含 Redis 的 C 语言版本客户端代码 hiredis、jemalloc 内存分配器代码、readline 性能的代替代码 linenoise,以及 lua 脚本代码。

(1.2) src 目录

这个目录外面蕴含了 Redis 所有功能模块的代码文件,也是 Redis 源码的重要组成部分。

(1.3) tests 目录

功能模块测试和单元测试的代码。
而在 Redis 的代码目录中,就将这部分代码用一个 tests 目录对立治理了起来。

Redis 实现的测试代码能够分成四局部,别离是单元测试(对应 unit 子目录),Redis Cluster 功能测试(对应 cluster 子目录)、哨兵功能测试(对应 sentinel 子目录)、主从复制功能测试(对应 integration 子目录)。
这些子目录中的测试代码应用了 Tcl 语言(通用的脚本语言)进行编写,次要目标就是不便进行测试。

(1.4) utils 目录

在 Redis 开发过程中,还有一些性能属于辅助性性能,包含用于创立 Redis Cluster 的脚本、用于测试 LRU 算法成果的程序,以及可视化 rehash 过程的程序。在 Redis 代码构造中,这些性能代码都被归类到了 utils 目录中对立治理。

(2) Redis 功能模块与源码对应

对于某个性能来说,个别包含了实现该性能的 C 语言文件(.c 文件)和对应的头文件(.h 文件)。比方,dict.c 和 dict.h 就是用于实现哈希表的 C 文件和头文件。

(2.1) 数据类型与数据结构

Redis 数据库提供了丰盛的键值对类型,其中包含了 String、List、Hash、Set 和 Sorted Set 这五种根本键值类型。
此外,Redis 还反对位图、HyperLogLog、Geo 等扩大数据类型。

而为了反对这些数据类型,Redis 应用了多种数据结构来作为这些类型的底层构造。

数据结构 Redis 数据类型 对应源码文件 备注
sds String t_string.c、sds.c、bitops.c Redis 的动静字符串实现
双向链表 List t_list.c Redis 的双端链表实现
压缩列表 List、Hash、Sorted Set ziplist.c
QuickList List、Hash、Sorted Set quicklist.c
整数汇合 Set intset.c 整数汇合数据结构
Zipmap Hash zipmap.c
哈希表 Hash t_hash.c
HyperLogLog HyperLogLog hyperloglog.c Redis 的 HyperLogLog 实现
GeoHash Geo geo.c、geohash.c、geohash_helper.c
位图 位图 bitops.c
Stream 时序数据 t_stream.c、rax.c、listpack.c

数据类型:

  • String(t_string.c、sds.c、bitops.c)
  • List(t_list.c、ziplist.c)
  • Hash(t_hash.c、ziplist.c、dict.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)

(2.2) 全局相干

全局:

  • 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)
  • 内存回收(expire.c、lazyfree.c)
  • 数据替换(evict.c)
  • 后盾线程(bio.c)
  • 事务(multi.c)
  • PubSub(pubsub.c)
  • 内存调配(zmalloc.c)
  • 双向链表(adlist.c)

初始化和主流程

Redis 在运行时是一个网络服务器实例,因而相应地就须要有代码实现服务器实例的初始化和主体管制流程,而这是由 server.h/server.c 实现的,Redis 整个代码的 main 入口函数也是在 server.c 中。
如果你想理解 Redis 是如何开始运行的,那么就能够从 server.c 的 main 函数开始看起。

事件驱动机制的网络通信框架

对于一个网络服务器来说,它还须要提供网络通信性能。Redis 应用了基于事件驱动机制的网络通信框架,波及的代码文件包含 ae.h/ae.c,ae_epoll.c,ae_evport.c,ae_kqueue.c,ae_select.c。

TCP 连贯

Redis 对 TCP 网络通信的 Socket 连贯、设置等操作进行了封装,这些封装后的函数实现在 anet.h/anet.c 中。这些函数在 Redis Cluster 创立和主从复制的过程中,会被调用并用于建设 TCP 连贯。

内存优化

Redis 是从三个方面来优化内存应用的,别离是内存调配、内存回收,以及数据替换。

首先,在内存调配方面,Redis 反对应用不同的内存分配器,包含 glibc 库提供的默认分配器 tcmalloc、第三方库提供的 jemalloc。Redis 把对内存分配器的封装实现在了 zmalloc.h/zmalloc.c。

其次,在内存回收上,Redis 反对设置过期 key,并针对过期 key 能够应用不同删除策略,这部分代码实现在 expire.c 文件中。同时,为了防止大量 key 删除回收内存,会对系统性能产生影响,Redis 在 lazyfree.c 中实现了异步删除的性能,所以这样,咱们就能够应用后盾 IO 线程来实现删除,以防止对 Redis 主线程的影响。

最初,针对数据替换,如果内存满了,Redis 还会依照肯定规定革除不须要的数据,这也是 Redis 能够作为缓存应用的起因。Redis 实现的数据替换策略有很多种,包含 LRU、LFU 等经典算法。这部分的代码实现在了 evict.c 中。

(2.3) 高可用

高可用 & 集群:

  • 长久化:RDB(rdb.c、redis-check-rdb.c)、AOF(aof.c、redis-check-aof.c)
  • 主从复制(replication.c)
  • 哨兵(sentinel.c)
  • 集群(cluster.c)

Redis 个别是作为内存数据库来应用的,然而它也提供了可靠性保障,这次要体现在 Redis 能够对数据做长久化保留,并且它还实现了主从复制机制,从而能够提供故障复原的性能。

长久化

Redis 的数据长久化实现有两种形式:内存快照 RDB 和 AOF 日志,别离实现在了 rdb.h/rdb.c 和 aof.c 中。留神,在应用 RDB 或 AOF 对数据库进行复原时,RDB 和 AOF 文件可能会因为 Redis 实例所在服务器宕机,而未能残缺保留,进而会影响到数据库复原。因而针对这一问题,Redis 还实现了对这两类文件的查看性能,对应的代码文件别离是 redis-check-rdb.c 和 redis-check-aof.c。

主从复制

Redis 把主从复制性能实现在了 replication.c 文件中。
另外你还须要晓得的是,Redis 的主从集群在进行复原时,次要是依赖于哨兵机制,而这部分性能则间接实现在了 sentinel.c 文件中。
其次,与 Redis 实现高可靠性保障的性能相似,Redis 高可扩展性保障的性能,是通过 Redis Cluster 来实现的,这部分代码也十分集中,就是在 cluster.h/cluster.c 代码文件中。
所以这样,咱们在学习 Redis Cluster 的设计与实现时,就会十分不便,不必在不同的文件之间来回跳转了。

(2.4) 辅助

辅助性能:

  • 提早统计(latency.c)
  • 慢日志(slowlog.c)
  • 告诉(notify.c)
  • 基准性能(redis-benchmark.c)

Redis 还实现了一些用于支持系统运维的辅助性能。
比方,为了便于运维人员查看剖析不同操作的提早产生起源,Redis 在 latency.h/latency.c 中实现了操作提早监控的性能;
为了便于运维人员查找运行过慢的操作命令,Redis 在 slowlog.h/slowlog.c 中实现了慢命令的记录性能,等等。

此外,运维人员有时还须要理解 Redis 的性能体现,为了反对这一指标,Redis 实现了对系统进行性能评测的性能,这部分代码在 redis-benchmark.c 中。
如果你想要理解如何对 Redis 发展性能测试,这个代码文件也值得一读。

参考资料

https://weikeqin.com/tags/redis/

退出移动版