架构原理
Redis 组件的系统架构如图所示,主要包括事件处理、数据存储及管理、用于系统扩展的主从复制/集群管理,以及为插件化功能扩展的 Module System 模块。
事件处理机制
Redis 中的事件处理模块,采用的是作者自己开发的 ae 事件驱动模型,可以进行高效的网络 IO 读写、命令执行,以及时间事件处理。
其中,网络 IO 读写处理采用的是 IO 多路复用技术,通过对 evport、epoll、kqueue、select 等进行封装,同时监听多个 socket,并根据 socket 目前执行的任务,来为 socket 关联不同的事件处理器。
当监听端口对应的 socket 收到连接请求后,就会创建一个 client 结构,通过 client 结构来对连接状态进行管理。在请求进入时,将请求命令读取缓冲并进行解析,并存入到 client 的参数列表。
然后根据请求命令找到 对应的redisCommand ,最后根据命令协议,对请求参数进一步的解析、校验并执行。Redis 中时间事件比较简单,目前主要是执行 serverCron,来做一些统计更新、过期 key 清理、AOF 及 RDB 持久化等辅助操作。
数据管理
redis 的内存数据都存在 redisDB 中。Redis 支持多 DB,每个 DB 都对应一个 redisDB 结构。Redis 的 8 种数据类型,每种数据类型都采用一种或多种内部数据结构进行存储。同时这些内部数据结构及数据相关的辅助信息,都以 kye/value 的格式存在 redisDB 中的各个 dict 字典中。
数据在写入 redisDB 后,这些执行的写指令还会及时追加到 AOF 中,追加的方式是先实时写入AOF 缓冲,然后按策略刷缓冲数据到文件。由于 AOF 记录每个写操作,所以一个 key 的大量中间状态也会呈现在 AOF 中,导致 AOF 冗余信息过多,因此 Redis 还设计了一个 RDB 快照操作,可以通过定期将内存里所有的数据快照落地到 RDB 文件,来以最简洁的方式记录 Redis 的所有内存数据。
Redis 进行数据读写的核心处理线程是单线程模型,为了保持整个系统的高性能,必须避免任何线程导致阻塞的操作。为此,Redis fock子线程,来处理容易导致阻塞的文件 close、fsync 等操作,确保系统处理的性能和稳定性。
在 server 端,存储内存永远是昂贵且短缺的,Redis 中,过期的 key 需要及时清理,不活跃的 key 在内存不足时也可能需要进行淘汰。为此,Redis 设计了 8 种淘汰策略,借助新引入的 eviction pool,进行高效的 key 淘汰和内存回收。