Redis 架构与事件驱动源码解析
1. 引言
Redis 是一款开源的高性能内存键值数据库,被广泛应用于缓存、消息队列、实时计算等场景。
它的高性能不仅来自于数据结构优化,更依赖于单线程事件驱动架构和I/O 多路复用机制。
本文将从以下方面深入解析 Redis 的架构与事件驱动模型:
- Redis 核心架构与单线程模型
- 事件驱动机制与源码解析
- 文件事件与时间事件的工作原理
- 客户端请求全链路流程
- 架构图与流程图增强版
目标读者:对 Redis 有基础了解,想深入理解其源码与事件驱动机制的开发者。
2. Redis 核心架构概览
Redis 内部可分为四个主要层次:
+-------------------------------------+
| Redis Server |
+-------------------------------------+
| Networking Layer |
| (TCP/Unix socket + EventLoop) |
+-------------------------------------+
| Command Execution Layer |
| (Parser, Dispatcher, Data Ops) |
+-------------------------------------+
| Data Structures & Storage |
| (Dict, List, SkipList, RDB/AOF) |
+-------------------------------------+
| Persistence & Replication |
| (RDB Snapshot, AOF, Master/Slave) |
+-------------------------------------+
特点:
- 单线程执行命令,避免数据竞争与锁开销;
- I/O 多路复用(epoll/kqueue/select)同时处理成千上万连接;
- 事件驱动模型将文件事件和时间事件统一调度。
3. Redis 事件驱动模型
Redis 事件模型由两类事件组成:
文件事件(File Event)
- 网络 I/O 事件,包括客户端读写、主从复制、Pub/Sub
时间事件(Time Event)
- 定时任务事件,如键过期、心跳检测、AOF fsync
3.1 事件循环数据结构
源码位于 ae.c
,核心结构体:
typedef struct aeEventLoop {
int maxfd; // 当前已注册的最大 fd
int setsize; // 可监听的最大 fd 数
aeFileEvent *events; // 文件事件数组
aeFiredEvent *fired; // 已触发的事件数组
aeTimeEvent *timeEventHead;// 时间事件链表
int stop; // 事件循环停止标记
} aeEventLoop;
事件循环核心流程:
while (!stop) {
1. 处理到期的时间事件
2. 计算下一次时间事件的超时时间
3. 调用 epoll_wait 等待文件事件
4. 执行所有触发的文件事件回调
}
4. 文件事件管理(File Event)
4.1 注册文件事件
当有客户端连接时,Redis 会通过 aeCreateFileEvent
注册文件事件:
aeCreateFileEvent(eventLoop, fd, AE_READABLE, readQueryFromClient, client);
- fd:客户端 socket
- AE\_READABLE:监听可读事件
- readQueryFromClient:事件触发时的回调函数
4.2 文件事件触发回调
epoll_wait
检测到 fd 可读时,事件循环调用回调:
void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
client *c = (client *)privdata;
int nread = read(fd, c->querybuf, ...);
if (nread <= 0) { ... } // 异常处理
processInputBuffer(c); // 解析命令并执行
}
4.3 特点
- 水平触发(Level Trigger)
- 单线程执行回调,避免锁
- I/O 与命令执行串行化,保证一致性
5. 时间事件管理(Time Event)
Redis 通过时间事件执行后台任务,如键过期和心跳检测。
核心函数 aeCreateTimeEvent
:
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
aeTimeProc *proc, void *clientData,
aeEventFinalizerProc *finalizerProc) {
// 计算触发时间
when_sec = now_sec + milliseconds/1000;
when_ms = now_ms + milliseconds%1000;
// 插入时间事件链表
timeEvent->when_sec = when_sec;
timeEvent->when_ms = when_ms;
...
}
典型时间事件:
serverCron()
:每 100ms 执行- 键过期检查
- AOF 状态更新
- 客户端超时检查
6. 主循环源码解析
server.c
主循环核心函数:
int main(int argc, char **argv) {
initServer(); // 初始化网络与数据结构
aeMain(server.el); // 启动事件循环
aeDeleteEventLoop(server.el); // 退出时清理
return 0;
}
aeMain
内部逻辑:
void aeMain(aeEventLoop *eventLoop) {
eventLoop->stop = 0;
while (!eventLoop->stop) {
aeProcessEvents(eventLoop, AE_ALL_EVENTS);
}
}
aeProcessEvents
会:
- 处理到期的时间事件
- 调用
epoll_wait
等待文件事件 - 执行回调
7. 客户端请求全链路示例
以 SET key value
为例:
1. epoll_wait 发现 socket 可读
2. 回调 readQueryFromClient
3. 解析 RESP 协议 -> 生成命令对象
4. 执行 setCommand -> 更新字典
5. 结果写入输出缓冲区
6. 注册写事件 AE_WRITABLE
7. 下次循环触发 sendReplyToClient 回复客户端
8. 架构图与流程图
8.1 Redis 总体架构
+-----------------------------+
| Client |
+-----------------------------+
|
v
TCP / Unix Socket
|
v
+----------------------------------------------------------+
| Redis Server |
|----------------------------------------------------------|
| Networking Layer |
| (EventLoop, epoll/kqueue/select) |
|----------------------------------------------------------|
| Command Execution Layer |
| Parser -> Dispatcher -> Data Operation (dict etc.) |
|----------------------------------------------------------|
| Data Structures & Storage Engine |
| Dict / SkipList / List / Hash / Set / Stream |
| + RDB / AOF / Replication |
|----------------------------------------------------------|
| Time Events & Background Tasks |
| (serverCron, AOF fsync, replication checks) |
+----------------------------------------------------------+
8.2 事件循环执行流程
while (!stop) {
1. 处理到期时间事件 (serverCron)
2. 计算下一时间事件超时
3. epoll_wait 等待文件事件
4. 执行所有触发的文件事件回调
}
8.3 文件事件处理流程
+-----------------------------------+
| epoll_wait detects fd readable |
+-----------------------------------+
|
v
+-----------------------------------+
| Callback: readQueryFromClient |
+-----------------------------------+
|
v
+-----------------------------------+
| Parse Redis Protocol (RESP) |
+-----------------------------------+
|
v
+-----------------------------------+
| Execute Command (setCommand) |
+-----------------------------------+
|
v
+-----------------------------------+
| Append result to output buffer |
+-----------------------------------+
|
v
+-----------------------------------+
| Register AE_WRITABLE event |
+-----------------------------------+
9. 总结
Redis 的高性能来源于:
- 单线程事件驱动架构:避免锁竞争;
- I/O 多路复用:高效处理成千上万连接;
- 文件事件与时间事件统一调度;
- 轻量回调驱动保证可预测的低延迟。
理解 Redis 的事件驱动机制后,你可以更轻松地分析其性能瓶颈,或实现定制的高性能服务端。
评论已关闭