Redis 6.0 的内存淘汰始终由主线程串行执行,多线程仅用于网络IO,不参与驱逐、过期检查或命令执行,以保障数据一致性与原子性。

Redis 6.0 的多线程不会影响内存淘汰机制的执行逻辑,因为所有键的驱逐(eviction)操作仍由主线程串行完成。
内存淘汰始终在主线程执行
Redis 6.0 引入的多线程仅用于网络 IO 层(read / write socket),不参与命令解析、执行、过期检查或 key 驱逐。这意味着:
-
maxmemory-policy(如allkeys-lru、volatile-ttl)的触发和实际删除动作,全部发生在主线程 - 即使启用了
io-threads 4,当内存达到maxmemory时,仍是主线程扫描、计算 LRU 时间戳、挑选 key 并调用dbDelete - 过期 key 的惰性删除(访问时检查)和定期删除(
activeExpireCycle)也完全不涉及 IO 线程
为什么不能把淘汰交给多线程做?
内存淘汰不是简单地“删掉一个 key”,它必须与命令执行严格串行,否则会破坏数据一致性:
- 如果某个
SET命令刚写入一个 key,IO 线程同时在另一个线程里把它删了,客户端会收到成功响应但数据却不存在 -
EXPIRE和TTL的语义依赖于全局时间视图,多线程并发更新expires字典可能引发竞态 - 淘汰过程需访问
redisDb结构体中的多个字段(如dict、expires、avg_ttl),跨线程共享这些结构需加锁,反而抵消性能收益
多线程对淘汰行为的间接影响
虽然淘汰本身不并行,但 IO 多线程会改变请求到达和排队节奏,从而影响淘汰发生的时机和压力分布:
- 高并发小请求下,IO 线程加速了请求入队,导致主线程更快积压待处理命令,可能更早触发
maxmemory限制 - 大 key 删除(如
DEL一个含百万成员的SET)仍会阻塞主线程 —— 这类操作不会因 IO 多线程而变快,反而可能因请求吞吐上升而更频繁地撞上淘汰阈值 - 若配置了
lazyfree-lazy-eviction yes,淘汰时的内存释放会异步化(交由bio线程),但这和 IO 线程无关,属于另一套后台机制
真正容易被忽略的是:很多人以为开了 io-threads 就等于“Redis 变成多线程数据库”了,其实主线程对数据结构的所有修改(包括淘汰)依然原子、串行、无锁——这点一旦混淆,就可能在设计分布式缓存策略或评估淘汰延迟时误判行为边界。


















