Skip to content

Redis Pipeline 模式

Redis 客户端和服务端之间采用 TCP 协议进行通信,基于 Request/Response 的一问一答模式,即请求一次响应一次。

普通模式

在普通模式下,一条 Redis 命令的简要执行过程如下:

  • 客户端发送一条命令给 Redis 服务端,阻塞等待服务端应答。
  • Redis 服务端接收到命令,执行命令。
  • Redis 服务端将结果返回给客户端。

完整请求的交互过程包括以下步骤:

  1. 客户端调用 write() 将消息写入操作系统为 socket 分配的 send buffer。
  2. 操作系统将 send buffer 中的内容发送到网卡,通过网关路由将内容发送到服务器网卡。
  3. 服务器网卡将接收到的消息写入操作系统为 socket 分配的 recv buffer。
  4. 服务器进程调用 read() 从 recv buffer 中读取消息并进行处理。
  5. 处理完成后,服务器调用 write() 将响应内容发送到 send buffer。
  6. 服务器将 send buffer 中的内容通过网卡发送到客户端。
  7. 客户端操作系统将网卡中的内容放入 recv buffer。
  8. 客户端进程调用 read() 从 recv buffer 中读取消息。

pipeline

普通模式的问题

在普通模式下,执行大量命令时,每个命令都需要经历上述流程,导致以下问题:

  • 每个命令的执行时间 = 客户端发送耗时 + 服务器处理耗时 + 服务器返回耗时 + 一个网络来回耗时(RTT)。
  • RTT 不稳定且难以控制,受网络线路拥堵、跳数等因素影响。
  • 频繁的 IO 系统调用(如 read()write())会增加开销,涉及用户态和内核态的切换。

Pipeline 模式

为了解决普通模式的性能问题,Redis 提供了 Pipeline 模式。Pipeline 允许客户端一次性发送多条命令,而无需等待每条命令的响应,服务端接收到所有命令后依次执行,并将结果打包后一次性返回给客户端。

Pipeline 的优点

  1. 减少 RTT:通过将多个命令打包为一次网络请求,减少了网络来回的次数。
  2. 减少 IO 调用次数:减少了频繁的 read()write() 系统调用,优化了性能。

基本使用

以下是 Pipeline 的 Java 使用示例:

java
Pipeline pipeline = jedis.pipelined();

for (int i = 0; i < 100; i++) {
    pipeline.rpush("rediskey", i + "");
}

pipeline.sync();

Pipeline 的核心思想是:客户端将一组 Redis 命令组装后通过一次 RTT 发送给服务器,服务器按顺序执行命令并将结果一次性返回。

Pipeline 注意事项

虽然 Pipeline 能显著提升性能,但在使用时需要注意以下几点:

  1. 命令数量不宜过多

    • 客户端会将命令写入内存缓冲区,命令过多可能导致缓冲区溢出或占用过多内存。
    • 官方推荐每次发送不超过 10,000 条命令,建议将大量命令拆分为多个小的 Pipeline。
  2. 仅支持单节点操作

    • Pipeline 一次只能运行在一个 Redis 节点上。在集群环境下,如果命令涉及多个节点,Pipeline 无法正常工作。
  3. 不保证原子性

    • Pipeline 仅是将多个命令打包发送,不保证所有命令作为一个整体执行。如果中间某条命令出错,剩余命令仍会继续执行。

Pipeline 与批量操作(如 MGET)的区别

  1. 适用场景

    • MGET 等批量操作适用于一个命令操作多个键值对。
    • Pipeline 适用于多条不同命令的批量执行。
  2. 原子性

    • MGET 是一个原子操作。
    • Pipeline 不保证原子性。
  3. 实现方式

    • MGET 是服务端实现。
    • Pipeline 是客户端和服务端共同实现。

Pipeline 与事务的区别

  1. 请求方式

    • Pipeline 是一次请求,服务端顺序执行后一次性返回结果。
    • 事务需要多次请求(先 MULTI,再执行多个命令,最后 EXEC),服务端顺序执行后一次性返回结果。
  2. 关注点

    • Pipeline 关注减少 RTT 和 IO 调用。
    • 事务关注一致性问题。

总结

Pipeline 是 Redis 提供的一种优化机制,通过减少网络往返和 IO 调用次数显著提升性能。但在使用时需要注意命令数量、节点限制和原子性问题。合理使用 Pipeline 可以在多命令执行场景下获得更好的性能表现。

TIP

原文作者: Max Fang

原文链接: http://www.immaxfang.com/redis-pipeline/

版权声明:本作品采用 署名-非商业性使用 4.0 国际 (CC BY-NC 4.0)进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。

粤ICP备20009776号