Redis 作为开源的高性能 Key-Value 存储系统,凭借 “快” 和 “灵活” 成为缓存、分布式锁等场景的首选。它不仅支持多种数据结构,还通过独特的线程模型和 I/O 机制保障高吞吐。本文将从 Redis 的基础特性出发,逐步拆解其执行流程、事件处理、线程模型等核心原理,帮你搞懂 Redis “快” 的本质。
一、Redis 基础:特性与存储结构
先明确 Redis 的核心优势和支持的数据类型,这是理解其应用场景的基础。
1. 为什么选择 Redis?4 大核心优点
- 极致性能:纯内存操作,命令执行速度极快,单机 QPS 可轻松突破 10 万;
- 丰富数据结构:不止 String,还支持 List、Hash、Set、Sorted-Set,适配多样业务场景(如排行榜用 Sorted-Set,购物车用 Hash);
- 操作原子性:单个命令或 Lua 脚本执行具有原子性,避免并发数据竞争;
- 场景适配广:可作缓存、分布式锁、消息队列(List 模拟)、计数器(String 自增)等,一站式解决多种需求。
2. 核心存储结构:5 种常用数据类型
Redis 的 Key 均为 String 类型,Value 支持 5 种核心结构,对应不同使用场景:
| 数据类型 | 特点 | 典型场景 |
|---|---|---|
| String | 二进制安全,可存文本 / 二进制 | 计数器、存储用户 Token |
| List | 有序可重复,基于链表实现 | 消息队列、最新消息排行 |
| Hash | 键值对集合,适合存储对象 | 购物车、用户信息存储 |
| Set | 无序不可重复,支持交集 / 并集 | 好友关系、去重统计 |
| Sorted-Set | 有序不可重复,按分数排序 | 排行榜、带权重的消息队列 |
二、Redis 执行流程:从命令输入到结果返回
一个 Redis 命令从发出到得到响应,需经历 “协议转换 - 网络传输 - 服务端处理 - 结果返回” 6 个步骤,流程清晰且高效:
- 命令输入:客户端(如 Java 的 Jedis)发起命令(如GET key);
- 协议转换:客户端将命令转为 Redis 专用的 RESP 协议(文本协议,简单易解析);
- Socket 发送:通过 Socket 将协议数据发送到 Redis 服务端;
- 服务端处理:服务端解析协议、执行命令、操作数据;
- Socket 返回:服务端将执行结果通过 Socket 回传给客户端;
- 结果返回:客户端解析 RESP 协议,将结果转为用户可理解的格式(如字符串、集合)。
三、Redis 事件处理:ae 模型 + I/O 多路复用
Redis 能高效处理大量客户端请求,核心依赖 “ae 事件驱动模型”,它整合了网络 I/O 事件和时间事件,通过 I/O 多路复用技术实现高并发。
1. ae 事件驱动模型:两类事件的统一管理
ae 模型是 Redis 的事件处理核心,负责调度两种事件:
- 网络 I/O 事件:处理客户端与服务端的 Socket 读写(如接收命令、返回结果);
- 时间事件:处理定时任务(如执行serverCron函数,做过期 Key 清理、AOF/RDB 持久化、统计更新等)。
2. 网络 I/O 处理:I/O 多路复用 + Reactor 模式
Redis 用 I/O 多路复用技术(封装了 epoll、kqueue、select 等,优先选高效的 epoll)同时监听多个 Socket,避免单线程阻塞,再结合 Reactor 模式分发事件,流程如下:
(1)Reactor 模式的 4 个核心组件
- 连接 Socket:监听客户端连接的 Socket(如默认 6379 端口对应的 Socket);
- I/O 多路复用程序:监控多个 Socket,当 Socket 有事件(可读 / 可写)时,将其加入队列;
- 文件事件分派器:从队列中取出有事件的 Socket,根据事件类型(可读 / 可写)分配对应的处理器;
- 事件处理器:处理具体事件,分 3 类:
-
- 连接应答处理器:处理客户端连接请求,创建client结构管理连接;
-
- 命令请求处理器:读取客户端发送的命令,解析后存入client的参数列表;
-
- 命令回复处理器:将命令执行结果写入 Socket,返回给客户端。
(2)文件事件的类型与优先级
- AE_READABLE 事件:Socket 可读(如客户端发命令、新客户端连接);
- AE_WRITABLE 事件:Socket 可写(如服务端要返回结果);
- 优先级:若一个 Socket 同时触发两种事件,优先处理 AE_READABLE(先读命令再回复,避免数据积压)。
(3)客户端连接与请求的处理流程
- 连接阶段:Redis 启动时,将 “连接应答处理器” 与监听 Socket 的 AE_READABLE 事件绑定;客户端发起连接,触发 AE_READABLE 事件,处理器创建新 Socket(对应该客户端),并将新 Socket 的 AE_READABLE 事件与 “命令请求处理器” 绑定;
- 请求阶段:客户端发命令,新 Socket 触发 AE_READABLE 事件,命令请求处理器读取并解析命令,找到对应的redisCommand(如GET对应getCommand),执行命令;
- 回复阶段:命令执行完后,新 Socket 触发 AE_WRITABLE 事件,命令回复处理器将结果写入 Socket,返回给客户端。
3. 时间事件:定时执行辅助任务
时间事件由serverCron函数统一处理,默认每 100 毫秒执行一次,主要做 3 件事:
- 清理过期 Key(遍历过期字典,删除超时 Key);
- 持久化操作(AOF 日志刷盘、RDB 快照生成);
- 统计更新(如客户端连接数、内存使用情况)。
四、Redis 线程模型:从单线程到多线程的演进
Redis 的线程模型经历了 “单线程→引入 BIO 后台线程→多 IO 线程” 的演进,核心是 “保证主线程高效,将慢任务异步化”。
1. Redis 单线程:主线程处理核心流程
- 单线程的定义:Redis 的网络 IO、命令解析与执行、数据读写等核心流程,均由一个主线程完成;
- 为什么用单线程:
-
- 避免多线程的上下文切换和共享资源竞争(如锁开销);
-
- Redis 的性能瓶颈是内存或网络,而非 CPU,单线程足够应对;
-
- 单线程模型简单,便于开发和调试;
- 单线程的问题:若主线程处理 “慢任务”(如大 Key 删除、文件关闭),会阻塞正常请求,导致服务卡顿。
2. BIO 后台线程:异步处理慢任务
为解决单线程卡顿问题,Redis 引入BIO(Background I/O)线程,采用 “生产者 - 消费者” 模型:主线程生产慢任务,BIO 线程消费处理,不阻塞主线程。
Redis 启动时创建 3 个 BIO 线程,对应 3 类任务队列:
- close 队列:处理文件关闭(如 AOF 重写后关闭旧 AOF 文件);
- fsync 队列:处理 AOF 日志刷盘(将内核缓冲区数据写入磁盘);
- lazyfree 队列:处理大 Key 删除(如删除元素数 > 64 的 List/Hash,避免主线程耗时)。
BIO 线程的工作流程:
- 主线程有慢任务时,创建任务对象,加锁后放入对应队列;
- 唤醒阻塞的 BIO 线程;
- BIO 线程从队列取任务处理,处理完后若队列空,再次阻塞等待新任务。
3. Redis 6.0 + 多 IO 线程:优化网络 IO 瓶颈
Redis 4.0 引入 BIO 线程后,主线程仍需处理 “命令解析” 和 “结果回复” 的网络 IO 操作 —— 高并发下,这两步会成为瓶颈。因此 Redis 6.0 引入多 IO 线程,专门处理网络 IO 的 “读解析” 和 “写回复”,核心流程如下:
多 IO 线程的协作过程(默认禁用,需设thread-do-reads=true):
- 分配 Socket:主线程接收客户端连接,将 Socket 放入全局队列,再分配给多个 IO 线程;
- 并行读解析:IO 线程并行读取 Socket 中的命令,解析为 Redis 可执行的格式;
- 主线程执行命令:IO 线程解析完后,主线程单线程执行所有命令(保证原子性);
- 并行写回复:主线程将执行结果写入缓冲区,IO 线程并行将结果回传给客户端。
多 IO 线程的特点:
- 仅网络 IO 的 “读解析” 和 “写回复” 用多线程,命令执行仍为单线程(避免并发问题);
- 充分利用多核 CPU,提升高并发场景下的 QPS;
- 默认禁用,需手动开启,建议 IO 线程数设为 CPU 核心数(如 4 核设io-threads 4)。
五、Redis “快” 的本质:4 个关键原因
综合以上原理,Redis “快” 的核心可总结为 4 点:
- 纯内存操作:数据存于内存,避免磁盘 IO 的耗时(磁盘 IO 速度是内存的万分之一);
- 单线程核心:无线程创建 / 销毁开销,无锁竞争,减少上下文切换;
- I/O 多路复用:单线程通过 epoll 等技术并发处理大量 Socket,不阻塞;
- 异步化慢任务:BIO 线程处理文件关闭、大 Key 删除等慢任务,不占用主线程资源。
总结
Redis 的设计围绕 “高效” 展开:用单线程保证核心流程的简洁与原子性,用 I/O 多路复用突破网络并发瓶颈,用 BIO 线程和多 IO 线程解决慢任务和 IO 瓶颈。理解这些原理,不仅能帮你更好地使用 Redis(如避免大 Key、合理配置 IO 线程数),还能掌握 “高性能系统设计” 的核心思路 —— 聚焦核心流程,将非核心任务异步化、并行化。