1.Redis 核心解析:从特性到执行原理的全方位梳理​

94 阅读8分钟

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 个步骤,流程清晰且高效:

image.png

  1. 命令输入:客户端(如 Java 的 Jedis)发起命令(如GET key);
  1. 协议转换:客户端将命令转为 Redis 专用的 RESP 协议(文本协议,简单易解析);
  1. Socket 发送:通过 Socket 将协议数据发送到 Redis 服务端;
  1. 服务端处理:服务端解析协议、执行命令、操作数据;
  1. Socket 返回:服务端将执行结果通过 Socket 回传给客户端;
  1. 结果返回:客户端解析 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)客户端连接与请求的处理流程

  1. 连接阶段:Redis 启动时,将 “连接应答处理器” 与监听 Socket 的 AE_READABLE 事件绑定;客户端发起连接,触发 AE_READABLE 事件,处理器创建新 Socket(对应该客户端),并将新 Socket 的 AE_READABLE 事件与 “命令请求处理器” 绑定;
  1. 请求阶段:客户端发命令,新 Socket 触发 AE_READABLE 事件,命令请求处理器读取并解析命令,找到对应的redisCommand(如GET对应getCommand),执行命令;
  1. 回复阶段:命令执行完后,新 Socket 触发 AE_WRITABLE 事件,命令回复处理器将结果写入 Socket,返回给客户端。

3. 时间事件:定时执行辅助任务

时间事件由serverCron函数统一处理,默认每 100 毫秒执行一次,主要做 3 件事:

  • 清理过期 Key(遍历过期字典,删除超时 Key);
  • 持久化操作(AOF 日志刷盘、RDB 快照生成);
  • 统计更新(如客户端连接数、内存使用情况)。

四、Redis 线程模型:从单线程到多线程的演进

Redis 的线程模型经历了 “单线程→引入 BIO 后台线程→多 IO 线程” 的演进,核心是 “保证主线程高效,将慢任务异步化”。

1. Redis 单线程:主线程处理核心流程

  • 单线程的定义:Redis 的网络 IO、命令解析与执行、数据读写等核心流程,均由一个主线程完成;
  • 为什么用单线程
    1. 避免多线程的上下文切换和共享资源竞争(如锁开销);
    1. Redis 的性能瓶颈是内存或网络,而非 CPU,单线程足够应对;
    1. 单线程模型简单,便于开发和调试;
  • 单线程的问题:若主线程处理 “慢任务”(如大 Key 删除、文件关闭),会阻塞正常请求,导致服务卡顿。

2. BIO 后台线程:异步处理慢任务

为解决单线程卡顿问题,Redis 引入BIO(Background I/O)线程,采用 “生产者 - 消费者” 模型:主线程生产慢任务,BIO 线程消费处理,不阻塞主线程。

Redis 启动时创建 3 个 BIO 线程,对应 3 类任务队列:

  • close 队列:处理文件关闭(如 AOF 重写后关闭旧 AOF 文件);
  • fsync 队列:处理 AOF 日志刷盘(将内核缓冲区数据写入磁盘);
  • lazyfree 队列:处理大 Key 删除(如删除元素数 > 64 的 List/Hash,避免主线程耗时)。

BIO 线程的工作流程:

  1. 主线程有慢任务时,创建任务对象,加锁后放入对应队列;
  1. 唤醒阻塞的 BIO 线程;
  1. BIO 线程从队列取任务处理,处理完后若队列空,再次阻塞等待新任务。

3. Redis 6.0 + 多 IO 线程:优化网络 IO 瓶颈

Redis 4.0 引入 BIO 线程后,主线程仍需处理 “命令解析” 和 “结果回复” 的网络 IO 操作 —— 高并发下,这两步会成为瓶颈。因此 Redis 6.0 引入多 IO 线程,专门处理网络 IO 的 “读解析” 和 “写回复”,核心流程如下:

多 IO 线程的协作过程(默认禁用,需设thread-do-reads=true):

  1. 分配 Socket:主线程接收客户端连接,将 Socket 放入全局队列,再分配给多个 IO 线程;
  1. 并行读解析:IO 线程并行读取 Socket 中的命令,解析为 Redis 可执行的格式;
  1. 主线程执行命令:IO 线程解析完后,主线程单线程执行所有命令(保证原子性);

image.png

  1. 并行写回复:主线程将执行结果写入缓冲区,IO 线程并行将结果回传给客户端。

image.png

多 IO 线程的特点:

  • 仅网络 IO 的 “读解析” 和 “写回复” 用多线程,命令执行仍为单线程(避免并发问题);
  • 充分利用多核 CPU,提升高并发场景下的 QPS;
  • 默认禁用,需手动开启,建议 IO 线程数设为 CPU 核心数(如 4 核设io-threads 4)。

五、Redis “快” 的本质:4 个关键原因

综合以上原理,Redis “快” 的核心可总结为 4 点:

  1. 纯内存操作:数据存于内存,避免磁盘 IO 的耗时(磁盘 IO 速度是内存的万分之一);
  1. 单线程核心:无线程创建 / 销毁开销,无锁竞争,减少上下文切换;
  1. I/O 多路复用:单线程通过 epoll 等技术并发处理大量 Socket,不阻塞;
  1. 异步化慢任务:BIO 线程处理文件关闭、大 Key 删除等慢任务,不占用主线程资源。

总结

Redis 的设计围绕 “高效” 展开:用单线程保证核心流程的简洁与原子性,用 I/O 多路复用突破网络并发瓶颈,用 BIO 线程和多 IO 线程解决慢任务和 IO 瓶颈。理解这些原理,不仅能帮你更好地使用 Redis(如避免大 Key、合理配置 IO 线程数),还能掌握 “高性能系统设计” 的核心思路 —— 聚焦核心流程,将非核心任务异步化、并行化。