Skip to content

线程模型

单线程命令执行 + IO 多路复用、6.0 多线程 IO、为什么单线程还快。

Updated View as Markdown
For humans

线程模型

Redis 的线程模型是面试高频题:命令执行单线程,网络 IO 多路复用,6.0 起 IO 可多线程。三句话讲清楚,再展开为什么。

事件循环

IO 多路复用 + 单线程事件循环

  • IO 多路复用:一个线程用 epoll 同时监听成千上万个 socket,只处理就绪的事件
  • 文件事件处理器:连接应答、命令请求、命令回复三类事件,全部串行处理
  • 因为命令执行是纯内存操作(微秒级),单线程足够快,还免去了锁竞争

为什么单线程

收益 说明
无锁 数据结构和命令都不用加锁,没有死锁
无上下文切换 不频繁切换线程
简单可靠 不存在并发 bug,调试容易

瓶颈分析:单机 Redis 的瓶颈在网络和内存,不在 CPU。CPU 通常个位数占用,所以多线程收益有限。

6.0 多线程 IO

6.0 引入多线程,但只处理网络读写

  • io-threads 配置(默认 1,需显式调大并开启 io-threads-do-reads 才生效,建议大于等于 4 核才开)
  • IO 线程负责 socket 读写和协议解析,命令执行仍然是单线程
  • 收益场景:大流量下网络读写开销明显时(尤其大批量 get/set)
  • 不开启的原因:命令执行仍是瓶颈时多线程无济于事

一句话:6.0 的多线程是“IO 多线程”,不是“执行多线程”,执行线程始终唯一。

单线程的代价

  • 慢命令阻塞一切:KEYS、大集合的 SMEMBERS、大 key 的删除(DEL)都会卡住整个实例
  • 解决办法:KEYS 换 SCAN、删除用 UNLINK(异步)、大 key 拆分(见大 key 篇)
  • 长 Lua 脚本同样阻塞

面试追问

  1. Redis 为什么单线程还快? 内存操作微秒级,单线程免锁免切换;瓶颈在网络和内存不在 CPU
  2. 单线程怎么处理并发? IO 多路复用,事件驱动,只处理就绪的连接
  3. 6.0 多线程改了什么? 网络 IO 读写多线程,命令执行仍单线程。io-threads 需显式开
  4. 哪些命令会阻塞? KEYS、SMEMBERS、DEL 大 key、长 Lua。用 SCAN、UNLINK、拆分替代
  5. 为什么不用多线程执行命令? 内存操作单线程已足够快,多线程引入锁竞争和复杂度,收益为负
Navigation

Type to search…

↑↓ navigate↵ selectEsc close