Valkey 中文社区

多线程与异步 I/O 原理

从单线程模型到 8.0 异步 I/O、9.1 IO 线程重构与 RDMA 实验的演进。

很多人对 Valkey/Redis 的第一个误解就是"单线程很慢"。实际上从 Redis 6 引入 I/O 线程开始,到 Valkey 8.0 的异步化重写,再到 9.1 的进一步流水线化,"单线程"早已只描述命令执行阶段。本文把线程模型拆开讲清楚:哪些环节并发了,哪些没有,调参时该看什么指标。

心智模型:三个阶段

任何一条命令在 Valkey 内部都要经历:

  1. 读取与解析(read + parse):从 socket 收字节,按 RESP 协议切出命令对象。
  2. 命令执行(exec):在键空间字典上 GET/SET/HINCRBY 等。
  3. 回写(write):把回复编码成 RESP,发回 socket。
阶段Redis 6 之前Redis 6 / 7Valkey 8.0Valkey 9.1
read+parse主线程串行I/O 线程并行(半双工)I/O 线程并行(异步)I/O 线程并行(深度流水线)
exec主线程串行主线程串行主线程串行主线程串行
write主线程串行I/O 线程并行(半双工)I/O 线程并行(异步)I/O 线程并行(深度流水线)

执行始终串行

不管开多少 I/O 线程,单条命令的执行依然在主线程上一个接一个地跑KEYS *、慢 Lua、SORT 大集合、未优化的正则 SCAN MATCH,仍然会阻塞所有其它请求。多线程解决的是网络瓶颈,不是计算瓶颈。

Valkey 8.0:异步 I/O 线程

Redis 6/7 的 I/O 线程是半双工的——主线程要等所有 I/O 线程批次完成才能进入下一轮事件循环。Valkey 8.0 把这个屏障去掉了:主线程与 I/O 线程通过批量队列异步交互,主线程一边执行命令,I/O 线程一边持续收发,互不阻塞。

效果在 AWS r7g 上很直观:相同硬件下从约 380K QPS 提升到约 1.2M QPS,约 3.2 倍。延迟分布也更平:p99 在高并发下不再被周期性 I/O 屏障拉高。

# valkey.conf
io-threads 8           # I/O 线程数,建议大约为物理核数的一半
io-threads-do-reads yes

调参经验值:

部署形态建议 io-threads
4 vCPU 小实例2
8 vCPU 通用4
16 vCPU 计算优化6–8
32 vCPU 以上8–12(再大边际收益急剧下降)

超过 12 之后,主线程的命令分发本身就会成为瓶颈,徒增上下文切换。

Valkey 9.1:IO 线程重构

9.1(2026 年 5 月)继续在 I/O 路径上深挖。官方基准(512B payload、9 个 IO 线程、客户端管道深度 10)单机达到 2.1M RPS,相比 8.x 同硬件再涨最多 17%。关键改动:

  • 进一步细化锁粒度,I/O 线程之间不再竞争共享缓冲。
  • 主线程批量调度算法引入预读窗口,把命令解析尽量与上一批执行重叠。
  • 回写阶段引入零拷贝路径,减少一次内核 buffer 拷贝。

2.1M RPS 单机

9.1 在 9 个 IO 线程下的官方基准,512B 字符串,pipeline=10。

主线程负载下降

同等负载下主线程 CPU 占比从 90%+ 降到 70% 左右,留出空间给计算密集型命令。

Valkey-over-RDMA(实验)

8.0 开始引入 RDMA 传输层(实验特性),在 RoCEv2 / InfiniBand 网络下绕过内核 TCP 栈。官方实验显示某些场景吞吐再涨 最高 275%,p99 延迟可下降到亚毫秒。前提:

  • 网卡支持 RDMA verbs;
  • 客户端使用支持 RDMA 的连接器(valkey-glide 计划支持);
  • 仅限同数据中心,跨 AZ 仍走 TCP。

目前 RDMA 仅在 valkey-server 与 valkey-cli 之间端到端验证,建议先在评估环境跑通再考虑生产。

双通道复制

8.0 还引入了"双通道复制":全量同步(RDB 传输)与增量同步(命令流)使用两条独立 TCP 连接,避免大 RDB 阻塞增量回放,副本追赶速度显著提升。配置:

repl-diskless-sync yes
dual-channel-replication-enabled yes

详见 集群内部

基准测试时的常见误区

别用 redis-benchmark 默认参数-c 50 -n 100000 对 8.0+ 来说太轻,跑不满 I/O 线程。试试 -c 256 -P 16 -n 5000000

单机端到端测延迟,要把客户端放在同 NUMA 节点。跨 NUMA 的 socket buffer 拷贝会污染测量。

io-threads-do-reads no 时只有写回多线程。如果你的负载读多写少,关掉这个开关会看到吞吐不升反降。

Pipeline 深度决定理论上限。深度 1 的客户端永远跑不到 2M RPS,因为往返延迟主导。压测要明确声明 pipeline 深度。

何时多线程帮不上你

症状真正瓶颈
p99 延迟稳定在 5ms+慢命令(KEYS、长事务、Lua)
单核 100%,其它核空闲执行阶段瓶颈,加 io-threads 无用
网卡打满已经到物理上限,考虑分片或 RDMA
客户端报 LOADING启动时 RDB/AOF 加载,线程多也帮不上

排查思路:先 LATENCY DOCTOR + SLOWLOG GET 50,再看 INFO commandstats 找最热的命令,最后才考虑调 io-threads。

小结

  • 单线程是关于"命令执行"的描述,不是关于整个进程的描述。
  • 8.0 的异步 I/O 是巨大跃迁,9.1 继续把曲线推上去。
  • 调 io-threads 之前先看清自己的瓶颈到底在 I/O 还是 CPU。
  • RDMA 与双通道复制是值得在评估环境试一试的两个新特性。

继续阅读 集群内部 了解多线程之外,分片层面如何把单机能力堆到 10 亿 RPS。

On this page