引言:Redis 的 pipeline(管道)功能在命令行中是没有的,但 redis 是支持 pipeline 的,而且在各个语言版的 client 中都有相应的实现。 由于网络开销延迟,就算 redis server 端有很强的处理能力,也会由于收到的 client 消息少,而造成吞吐量小。当 client 使用 pipelining 发送命令时,redis server 必须将部分请求放到队列中(使用内存),执行完毕后一次性发送结果;如果发送的命令很多的话,建议对返回的结果加标签,当然这也会增加使用的内存;
Pipeline 在某些场景下非常有用,比如有多个 command 需要被“及时的”提交,而且他们对相应结果没有互相依赖,对结果响应也无需立即获得,那么 pipeline 就可以充当这种“批处理”的工具;而且在一定程度上,可以较大的提升性能,性能提升的原因主要是 TCP 连接中减少了“交互往返”的时间。

一、Pipeline简介

Redis 使用的是客户端-服务器(CS)模型和请求/响应协议的 TCP 服务器。这意味着通常情况下一个请求会遵循以下步骤:
客户端向服务端发送一个查询请求,并监听 Socket 返回,通常是以阻塞模式,等待服务端响应。
服务端处理命令,并将结果返回给客户端。
管道(pipeline)可以一次性发送多条命令并在执行完后一次性将结果返回,pipeline 通过减少客户端与 redis 的通信次数来实现降低往返延时时间,而且 Pipeline 实现的原理是队列,而队列的原理是时先进先出,这样就保证数据的顺序性。
通俗点来讲,pipeline就是把一组命令进行打包,然后一次性通过网络发送到Redis。同时将执行的结果批量的返回回来。

二、适用场景

有些系统可能对可靠性要求很高,每次操作都需要立马知道这次操作是否成功,是否数据已经写进 redis 了,那这种场景就不适合。
  还有的系统,可能是批量的将数据写入 redis,允许一定比例的写入失败,那么这种场景就可以使用了,比如10000条一下进入 redis,可能失败了2条无所谓,后期有补偿机制就行了,比如短信群发这种场景,如果一下群发10000条,按照第一种模式去实现,那这个请求过来,要很久才能给客户端响应,这个延迟就太长了。如果客户端请求设置了超时时间5秒,那肯定就抛出异常了,而且本身群发短信要求实时性也没那么高,这时候用 pipeline 最好了。

三、代码案例

private void setCache(List<String> names, String key) {
        Pipeline pipeline = redis.pipelined();
        for (String name : names) {
            pipeline.zadd(key, name, score);
        }
        pipeline.expire(key, CACHE_EXPIRE_SECONDS);
        pipeline.sync();
}

pipelined.sync()将一次性的异步命令发送到redis,不关注执行结果。
pipeline.syncAndReturnAll ();将返回执行过的命令返回的List列表结果

四、比较普通模式与 PipeLine 模式的执行速度

/*
 * 测试普通模式与 PipeLine 模式的效率: 
 * 测试方法:向 redis 中插入 10000 组数据
 */
public static void testPipeLineAndNormal(Jedis jedis)
		throws InterruptedException {
	Logger logger = Logger.getLogger("javasoft");
	long start = System.currentTimeMillis();
	for (int i = 0; i < 10000; i++) {
		jedis.set(String.valueOf(i), String.valueOf(i));
	}
	long end = System.currentTimeMillis();
	logger.info("the jedis total time is:" + (end - start));

	Pipeline pipe = jedis.pipelined(); // 先创建一个 pipeline 的链接对象
	long start_pipe = System.currentTimeMillis();
	for (int i = 0; i < 10000; i++) {
		pipe.set(String.valueOf(i), String.valueOf(i));
	}
	pipe.sync(); // 获取所有的 response
	long end_pipe = System.currentTimeMillis();
	logger.info("the pipe total time is:" + (end_pipe - start_pipe));
	
	BlockingQueue<String> logQueue = new LinkedBlockingQueue<String>();
	long begin = System.currentTimeMillis();
	for (int i = 0; i < 10000; i++) {
		logQueue.put("i=" + i);
	}
	long stop = System.currentTimeMillis();
	logger.info("the BlockingQueue total time is:" + (stop - begin));
}

pipeline redis 实现原理 redis lua pipeline_System


参考文章:分布式缓存Redis之Pipeline(管道)