Redis 架构与事件驱动源码解析

1. 引言

Redis 是一款开源的高性能内存键值数据库,被广泛应用于缓存、消息队列、实时计算等场景。
它的高性能不仅来自于数据结构优化,更依赖于单线程事件驱动架构I/O 多路复用机制

本文将从以下方面深入解析 Redis 的架构与事件驱动模型:

  1. Redis 核心架构与单线程模型
  2. 事件驱动机制与源码解析
  3. 文件事件与时间事件的工作原理
  4. 客户端请求全链路流程
  5. 架构图与流程图增强版

目标读者:对 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)    |
+-------------------------------------+

特点

  1. 单线程执行命令,避免数据竞争与锁开销;
  2. I/O 多路复用(epoll/kqueue/select)同时处理成千上万连接;
  3. 事件驱动模型将文件事件和时间事件统一调度。

3. Redis 事件驱动模型

Redis 事件模型由两类事件组成:

  1. 文件事件(File Event)

    • 网络 I/O 事件,包括客户端读写、主从复制、Pub/Sub
  2. 时间事件(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 会:

  1. 处理到期的时间事件
  2. 调用 epoll_wait 等待文件事件
  3. 执行回调

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 的高性能来源于:

  1. 单线程事件驱动架构:避免锁竞争;
  2. I/O 多路复用:高效处理成千上万连接;
  3. 文件事件与时间事件统一调度
  4. 轻量回调驱动保证可预测的低延迟。

理解 Redis 的事件驱动机制后,你可以更轻松地分析其性能瓶颈,或实现定制的高性能服务端。


最后修改于:2025年07月29日 13:00

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日