必须同时设置io-threads≥2和io-threads-do-reads yes才能启用读多线程,缺一不可;二者均不支持热更新,需config rewrite后重启,并通过info threads验证io_threads_num、io_threads_do_reads和io_threads_active均为1。

io-threads-do-reads yes 是开启读多线程的硬性开关
只配 io-threads 4 不会启用读并行,Redis 默认关闭读线程处理,io-threads-do-reads 必须显式设为 yes 才能让 I/O 线程真正参与请求读取。漏掉这一步,整个 pipeline 就卡在第一步:主线程还在等 read() 返回,后续命令根本进不来。
这个参数和 io-threads 是绑定生效的组合项,缺一不可:
-
io-threads值必须 ≥ 2(设为 1 等价于禁用) -
io-threads-do-reads必须为yes,默认是no - 两个参数都不支持
CONFIG SET热更新,改完必须执行CONFIG REWRITE并重启实例
验证是否真正在跑读线程
别信配置文件,要看运行时指标。连上 Redis 执行:
INFO threads
检查输出中这两项:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
io_threads_num是否等于你设的数值(比如 4) -
io_threads_do_reads是否为1(不是字符串 "yes",是整数 1) -
io_threads_active是否为1(表示线程池已启动)
再开一个终端跑 top -H -p $(pgrep redis),能看到多个 io_thread_* 线程的 CPU 占用随流量上升——这才是真实生效的信号。
线程数设多少才不翻车
不是越多越好,超配反而拉垮:
- 推荐值 =
min(4, CPU物理核心数 × 0.7);8 核机器设 4~5,16 核也别超 6 - 设成 8 或 16 在普通服务器上大概率触发频繁上下文切换,
%sy(系统态 CPU)飙升,QPS 反而下降 - 连接数 ÷ 线程数
- NUMA 架构下必须配合
server_cpulist绑定同 node 的 CPU,否则跨 node 访存延迟抵消多线程收益
大连接数下容易被忽略的副作用
开启 io-threads-do-reads yes 后,每个新连接都会绑定一个 I/O 线程并分配独立缓冲区,短连接风暴会让内存 RSS 暴涨:
- 每连接 socket 缓冲区(受
net.ipv4.tcp_rmem影响)、client 结构体、TLS 上下文(如启用)全量叠加 - 连接数超 5000 时,used_memory_rss 中可能只有 30%~40% 来自键值,其余全是连接元数据
- 客户端不用连接池、服务端
timeout设得过大(比如 300),会导致大量空闲连接长期挂起,线程无法复用 - 此时调大线程数只会加重线程栈开销(默认 2MB/线程),建议优先压连接生命周期,再调线程数
真正卡点不在“能不能开”,而在“开了之后连接怎么管”。没压住连接数,多线程只是把内存溢出从命令执行阶段提前到了连接建立阶段。










