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 与紧凑编码,从底层结构解释内存占用和复杂度。