Redis 管道Pipeline机制详解

474 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

客户端可以一次性发送多个请求而不用等待服务器的响应,等所有命令都发送完毕后再一次性读取服务的响应,这样可以极大的降低多条命令执行的网络传输开销,管道执行多条命令的网络开销实际上只相当于一次命令的网络开销。

使用 pipeline 方式打包命令发送,redis 必须在处理完成所有命令前先缓存起来所有命令的处理结果。打包的命令越多,消耗内存也越多,所以并不是打包命令越多越好。

pipeline是客户端的行为,对于服务器来说是透明的,可以认为服务器无法区分客户端发送来的查询命令是以普通命令的形式还是以pipeline的形式发送到服务器的;

应用pipeline可以提服务器的吞吐能力,并提高Redis处理查询请求的能力。

但是这里存在一个问题,当通过pipeline提交的查询命令数据较少,可以被内核缓冲区所容纳时,Redis可以保证这些命令执行的原子性。然而一旦数据量过大,超过了内核缓冲区的接收大小,那么命令的执行将会被打断,原子性也就无法得到保证。因此pipeline只是一种提升服务器吞吐能力的机制,如果想要命令以事务的方式原子性的被执行,还是需要事务机制,或者使用更高级的脚本功能以及模块功能。

代码示例

try (Jedis jedis = jedisPool.getResource()) {
    jedis.set("name", "beifeng");
    Pipeline pipelined = jedis.pipelined();
    for (int i = 0; i < 100; i++) {
        pipelined.incr("count");
        pipelined.set("pp:key:" + i, "beifeng-" + i);
        // bitmap 不存在-1的索引,模拟报错场景
        pipelined.setbit("bitmap", -1, true);
    }
    // 获取执行结果
    List<Object> objects = pipelined.syncAndReturnAll();
    System.out.println(objects);
}

pipeline 发送的每个命令都会被 server 立即执行,如果执行失败,将会在此后的响应中得到信息,也就是说前面的命令失败后面的命令不会有影响,继续执行;所以 pipeline 是非原子操作