跳到正文
Elaine Blog
返回

Redis 线程模型、I/O 多路复用与命令原子性

Redis 与缓存工程

Redis 快的主要原因是内存数据结构、事件驱动网络和短小命令,而不是一句“单线程”。核心命令通常按顺序执行,但网络 I/O、持久化、释放内存等工作可以使用其他线程;慢命令仍会阻塞命令执行路径。

Table of contents

Open Table of contents

一条请求如何经过 Redis

客户端连接
  → 操作系统通知哪些 Socket 已就绪
  → 事件循环读取并解析命令
  → 执行数据结构操作
  → 写入响应缓冲区
  → Socket 可写时发送结果

I/O 多路复用让一个事件循环监视许多连接,只有就绪连接才进入处理。它减少“一连接一线程”的调度开销,但不能把昂贵命令自动变成并行任务。

原子到底保证什么

单条命令执行期间不会与另一条命令交错,所以 INCR counter 可以安全递增。客户端先 GET、在 Java 中计算、再 SET 是三步,其他请求可插入其中,会发生覆盖。

多步逻辑可用 Lua 脚本、事务命令或一个更合适的原子命令表达。Lua 在服务器执行时也会阻塞其他命令,因此脚本要短、输入有界,不能把批处理业务整体搬进脚本。

Pipeline 只减少网络往返,不提供事务隔离;MULTI/EXEC 将命令排队后连续执行,但运行时错误不会像关系数据库事务那样自动回滚先前命令。不要把三者混为一谈。

哪些操作会阻塞

大 Key 的全量读取/删除、对超大集合做聚合、长 Lua、同步磁盘工作、输出缓冲区膨胀和网络拥塞都可能造成延迟。KEYS * 会遍历整个键空间,生产排查应优先使用增量 SCAN,并控制每批数量。

客户端也要设置连接、命令和总请求超时。超时之后不要盲目重试非幂等命令,因为服务端可能已经执行,只是响应丢失。

下一步

继续阅读07-03 SDS、Dict、SkipList 与紧凑编码,从底层结构解释内存占用和复杂度。


分享这篇文章:

上一篇
Redis 数据类型与典型建模
下一篇
SDS、Dict、SkipList 与紧凑编码