本文是大数据系列第 48 篇,深入解析 Redis 的通信协议 RESP 和基于 Reactor 模式的事件驱动架构。

完整图文版(含截图):CSDN 原文 | 掘金

为什么要了解 Redis 底层通信?

Redis 以”单线程处理命令却能支撑高并发”著称。这背后依赖两个核心设计:RESP 协议保障高效、轻量的网络通信;Reactor 事件驱动模型实现单线程多路复用 I/O。理解这两者,是深度调优 Redis 和排查连接问题的基础。

RESP 协议(Redis Serialization Protocol)

RESP 是 Redis 自定义的轻量序列化协议,设计目标是简单、高效、可读性好、对二进制数据安全。

五种数据类型

类型首字节示例
简单字符串(Simple String)++OK\r\n
错误(Error)--ERR unknown command\r\n
整数(Integer)::1000\r\n
批量字符串(Bulk String)$$6\r\nfoobar\r\n
数组(Array)**2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n

所有数据以 \r\n(CRLF)结尾,格式固定、解析成本极低。

请求与响应示例

客户端执行 SET mykey myvalue,实际发送的字节流:

*3\r\n
$3\r\nSET\r\n
$5\r\nmykey\r\n
$7\r\nmyvalue\r\n

服务端返回:

+OK\r\n

RESP 的设计使得协议解析可以用几十行代码实现,极大降低了客户端库的开发难度。

通信模式

串行模式(Serial)

客户端发送请求,等待响应,再发下一个请求。每次 RTT(Round-Trip Time)都是纯网络开销,吞吐量受限于延迟。

Pipeline 模式

Pipeline 允许客户端批量发送多个命令,不等待每条命令的响应,服务端处理完毕后统一返回结果,将多次 RTT 压缩为一次。

Jedis Pipeline 示例:

Jedis redis = new Jedis("host", 6379);
Pipeline pipe = redis.pipelined();
for (int i = 0; i < 50000; i++) {
    pipe.set("key_" + i, String.valueOf(i));
}
pipe.sync(); // 统一发送并等待所有响应

Pipeline 在批量写入场景下性能可提升 10 倍以上,但注意单个 Pipeline 中命令数量不宜过多(建议 100-1000 条),避免一次性传输数据量过大。

Reactor 事件驱动模型

Redis 采用单线程 + I/O 多路复用架构,通过 Reactor 模式实现对大量并发连接的高效处理。

I/O 多路复用机制对比

机制平台最大 FD扫描方式性能
select跨平台1024(FD_SETSIZE)线性扫描
poll跨平台无限制线性扫描
epollLinux~100,000事件通知
kqueueBSD/macOS~100,000事件通知

Redis 在 Linux 下使用 epoll,只在有事件就绪时唤醒,不做无效轮询,是支撑高并发的关键。

核心数据结构

aeEventLoop(事件循环)
├── FileEvent[]  ← 监听 socket 的读写事件
└── TimeEvent[]  ← 定时任务(如 serverCron)

请求处理完整流程

1. 客户端 connect → epoll 检测到连接事件
2. acceptTcpHandler 建立连接,注册读事件
3. 客户端发送命令 → 触发可读事件
4. readQueryFromClient 读取数据,按 RESP 协议解析命令
5. 命令处理器执行业务逻辑,写入响应缓冲区
6. 注册写事件 → sendReplyToClient 将结果发送回客户端

整个流程在单线程事件循环中串行执行,不存在线程切换和锁竞争,这正是 Redis 命令处理高性能的根源。

单线程架构的优缺点

优点:

  • 无上下文切换开销,无锁竞争
  • 数据结构实现无需考虑并发安全
  • 代码逻辑简单,易于维护和调试

局限性:

  • 受限于单核 CPU,无法利用多核
  • 耗时命令(如 KEYS *LRANGE 大范围)会阻塞整个事件循环
  • 大 key 的读写和删除操作会导致其他请求延迟上升

Redis 6.0 多线程 I/O

Redis 6.0 引入了多线程网络 I/O(读取请求、发送响应由多线程处理),但命令执行仍是单线程。这解决了网络 I/O 成为瓶颈的问题,同时保持了命令执行的串行性,无需引入复杂的并发控制。

# redis.conf 开启多线程 I/O(默认关闭)
io-threads 4
io-threads-do-reads yes

总结

Redis 的高性能来自三个层面的精巧设计:

  1. RESP 协议:轻量高效,解析简单,支持 Pipeline 批处理
  2. epoll 多路复用:单线程监听数万连接,只处理就绪事件
  3. Reactor 事件循环:将网络 I/O 和命令执行统一在单线程中,避免并发开销