有利于减小高并发量情况下对性能的影响
根据论文 SEDA: An Architecture for Well-Conditioned, Scalable Internet Services 的测试结果显示,相比一个连接分配一个线程的模型,Reactor 模式(固定线程数)在连接数增大的情况下吞吐量不会明显降低,延时也不会也受到显著的影响 。
二、事件循环的 Redis 实现
下面开始,会对 Redis 如何实现事件循环进行说明,会涉及到一些源码的实现部分,如果不感兴趣可以直接跳到第三节看 Redis 怎么利用事件处理模型来处理具体的命令 。
2.1 Redis 事件循环 Event Loop
Redis 的事件循环,最直观的理解,就是一个在不断等待事件的一个无限循环,直到 Redis 程序退出 。
Redis 实现事件循环主要涉及三个源码文件:server.c, ae.c, networking.c 。
- server.c 的 main()函数是整个 Redis 程序的开始,我们也从这里开始观察 Redis 的行为 。
- ae.c实现事件循环和事件的相关功能 。
- networking.c则负责处理网络IO相关的功能 。

文章插图
a. 初始化 Redis 配置
初始化的过程主要做三个事情:
- 加载配置
- 创建事件循环
- 执行事件循环
// 0. 定义服务器主要结构体, 加载服务器配置struct redisServer server;initServerConfig();loadServerConfig();// 1. 根据配置参数初始化,initServer() { // 1.1 实际创建事件循环 server.el = aeCreateEventLoop(); // 1.2 为事件循环注册一个可读事件,用于响应外部客户端请求 aeCreateFileEvent(server.el, AE_READABLE, acceptTcpHandler)}// 2. 执行事件循环,等待连接和命令请求aeMain(server.el);初始化过程中被创建的server.el包含了两个事件的列表,它的结构体实现如下:
typedef struct aeEventLoop{ aeFileEvent events[AE_SETSIZE]; /* 注册的事件,被 eventloop 监听 */ aeFiredEvent fired[AE_SETSIZE]; /* 有读写操作需要执行的事件(就绪事件) */} aeEventLoop;b. 创建事件循环
主循环体aeMain()在ae.c文件中被实现,简化后的代码如下:
void aeMain(aeEventLoop *eventLoop) { while (!eventLoop->stop) { aeProcessEvents(eventLoop, AE_ALL_EVENTS); }}事件循环主要就是一个while循环,不断去轮询是否有就绪的事件需要处理,具体的处理函数是aeProcessEvents,接下来会有对这个函数有更详细的介绍 。
c. 创建用于监听端口的事件
在上述 Redis 在初始化时,程序会创建一个关联了acceptTcpHandler处理器的可读事件:
aeCreateFileEvent(server.el, AE_READABLE, acceptTcpHandler)这个可读事件注册到事件循环中,就实现了 Redis 对外提供的服务地址和端口的连接服务 。具体的内容下一个小节事件处理器中介绍 。
2.2 事件处理器 Event Handler
所有事件被创建时,都会关联一个处理器 (handler),并注册到事件循环中,事件处理器用于具体的读写操作 。
Redis 的常用几个事件处理器有:
- 响应连接的处理器acceptTcpHandler()
- 读取客户端命令的处理器readQueryFromClient()
- 返回处理结果的处理器sendReplyToClient()
一个客户端一次正常的连接和命令操作流程,可以通过上述三个处理器完成 。

文章插图
当 Redis 需要监听某个套接字的时候,就会创建一个事件,并注册到事件循环中进行监听,Redis 将处理器以参数的方式关联到事件中 。
比如以下是注册一个可读事件的操作:
aeCreateFileEvent(server.el, fd, AE_READABLE, readQueryFromClient, c)
- server.el:事件循环 eventloop,一个服务器只有一个el
- fd:表示这个客户端连接的文件描述符,每个客户端连接对应一个
- AE_READABLE:表示这是一个可读事件,可以理解为客户端准备进行写操作
- readQueryFromClient: 这个事件关联的处理器,当事件就绪后,就会调用此处理器
- c:表示这个客户端在Redis中指向的变量
可以看到整个过程中事件循环和不同处理器之间是解耦的,互不干扰 。这样实现提高了代码的简洁和重用 。
2.3 事件处理 Process Events
推荐阅读
- 关于redis学会这8点就够了
- Redis实现统计网站访问人数的功能
- 利用Redis黑进目标系统
- 抖音短视频的核心是什么?
- Redis混合存储产品与架构介绍
- MAC与IP不得不说的故事--深入ARP工作原理
- redis解析:缓存及常见问题
- 一文弄懂视频网站CDN的访问调度原理
- 设计规范篇 苹果手机拆机与原理图对比分析
- 点点滴滴学5G——一文读懂5G中BWP的原理
