您的位置:首页 > 教育 > 锐评 > Redis 7.x 系列【19】管道

Redis 7.x 系列【19】管道

2025/6/21 14:42:34 来源:https://blog.csdn.net/qq_43437874/article/details/139666943  浏览:    关键词:Redis 7.x 系列【19】管道

有道无术,术尚可求,有术无道,止于术。

本系列Redis 版本 7.2.5

源码地址:https://gitee.com/pearl-organization/study-redis-demo

文章目录

    • 1. 往返时间
    • 2. 管道技术
    • 3. 代码演示
    • 4. 其他批处理
      • 4.1 原生批处理命令
      • 4.2 事务
      • 4.3 脚本

1. 往返时间

官方文档

Redis 是一种基于 CS 模型以及请求/响应协议的TCP服务。通常情况下一个请求会遵循以下步骤:

  • 客户端向服务端发送一个请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
  • 服务端处理命令,并将结果返回给客户端。

例如,一个客户端发送四次命令的流程如下所示:
在这里插入图片描述
客户端和服务端之间通过网络进行连接通信,无论网络延迟如何,数据包从客户端到服务端的传输,以及从服务端回到客户端的响应,都需要一定的时间,这段时间被称为往返时间RTT)。

当客户端需要连续执行许多请求时,例如向同一列表添加多个元素或者将数据库填充多个键,往返时间如何影响性能就很容易理解了。例如,如果往返时间为250毫秒(非常慢的连接),即使服务端能够每秒处理10万个请求,客户端每秒也只能发送四个请求。

2. 管道技术

对于上述问题,Redis 提供了管道(Plpeline)技术,允许客户端将多个命令一次性发送给服务器,而不需要等待每个命令的回复。这样可以减少每条命令的网络延迟时间,特别适合需要发送大量命令的场景。

执行流程如下所示:
在这里插入图片描述

管道技术不仅减少了 RTT ,并且极大地提升了在 Redis 服务器上每秒可以执行的操作数量。

使用注意事项:

  • 使用管道时,命令只是会依次以行,不保证原子性,如果其中某个命令令发生异常,将会继续执行
  • 组装的命令个数不能太多,不然数据量太大时,客户端阻塞的时间可能过久,同时服务端此时也被迫回复一个队列答复,占用很多内存
  • 需要发送大量的命令时,需要按照合理数量分批次的处理,例如一次发送10K的命令,读取回复后,后再发送另一个10k的命令。

3. 代码演示

下面代码中,使用 Jedis 插入 10000Key

    public static void main(String[] args) {// 创建连接池JedisPool pool = new JedisPool("localhost", 6379,"default","123456");// 获取客户端try (Jedis jedis = pool.getResource()) {// 1. 不使用管道, 插入 10000 个 Keylong startTime = System.currentTimeMillis();for (int i = 10000; i > 0; i--) {jedis.set("key" + i, String.valueOf(i));}System.out.println("不使用管道执行时间:" + ( System.currentTimeMillis()-startTime)+"毫秒");// 2. 使用管道startTime = System.currentTimeMillis();Pipeline pipelined = jedis.pipelined();for (int i = 10000; i > 0; i--) {pipelined .set("key" + i, String.valueOf(i));}System.out.println("使用管道执行时间:" + ( System.currentTimeMillis()-startTime)+"毫秒");}}

可以看到,在使用了管道后,执行时间缩短了近 30 倍:

不使用管道执行时间:793毫秒
使用管道执行时间:26毫秒

对于查询命令,当然也可以使用管道,不过结果值是批量返回的:

            Pipeline pipelined = jedis.pipelined();for (int i = 10000; i > 0; i--) {//pipelined .set("key" + i, String.valueOf(i));pipelined.get("key" + i);}// 获取执行结果List<Object> results = pipelined.syncAndReturnAll();

4. 其他批处理

除了管道, Redis 还提供了其他批处理方式,可以根据具体需求选择合适的方式来操作 Redis

4.1 原生批处理命令

Redis 提供了两个常用的原生命令来处理多个键的操作:

  • MGET: 同时获取多个键的值
  • MSET: 同时设置多个键的值

MGETMSET 命令都是原子操作,即要么全部执行成功,要么全部执行失败。适合于需要一次性获取或设置多个键值对的场景。

示例:

MGET key1 key2 key3
MSET key1 value1 key2 value2 key3 value3

4.2 事务

通过事务机制,可以将多个命令打包在一起执行,事务中的所有命令要么全部执行,要么全部不执行。

示例:

MULTI
SET key1 value1
GET key2
INCR key3
EXEC

4.3 脚本

通过 Redis 脚本,可以将多个命令打包成一个原子操作,确保在执行期间不会被其他命令打断。

示例:

local result1 = redis.call('SET', KEYS[1], ARGV[1])
local result2 = redis.call('GET', KEYS[2])
local result3 = redis.call('INCR', KEYS[3])
return {result1, result2, result3}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com