说pipeline之前首先明确两点
redis的1次网络命令的耗时为 :1次网络时间 + 1次命令执行时间
redis的n次网络命令的耗时为: n次网络时间 + n次命令执行时间
有了上面的计算,我们知道,如果我们要对redis进行一个批量的操作,是很耗时的,但我们又知道,redis的命令执行时间通常来说是非常快的,最关键的耗时其实是在网络传输的时间上。pipeline就是用来将n次的网络时间优化为一次的网络时间。
pipeline是将n个命令一次性打包,发送到服务端逐个执行,耗时为:1次网络时间 + n次命令时间
由此看来,pipeline可以大大减小我们网络时间的开销,但是在使用时,仍然需要注意一个点,即 pipeline每次的条数需要控制(网络环境相对复杂)
下面来看一个插入10000条hash对比
没有使用pipline 耗时 50s
Jedis jedis = new Jedis("127.0.0.1",6379);
for( int i=0; i<10000; i++){
jedis.hset("hashkey:"+i,"field"+i,"value"+i);
}
使用pipline 耗时 0.7s
Jedis jedis = new Jedis("127.0.0.1",6379);
for(int i=0; i<100; i++){
Pipeline pipeline = jedis.pipelined();
for(int j=i*100; j<(i+1)*100; j++){
pipeline.hset("hashkey:"+j,"field"+j,"value"+j);
}
pipeline.syncAndReturnAll();
}
Pipeline与原生M操作区别
我们知道redis原生有类似 mget mset的批量操作命令,这些命令都是原子的,即会阻塞其他的命令,知道命令完成返回。而pipeline的每一条命令是拆分过的(非原子),假设打包1000个命令的pipeline传到服务端,则服务端会把pipeline的每个命令当成原子。但无论是pipeline还是M操作 返回的结果都是一样的。
需要注意的点
1.注意没次pipeline携带的数据量(网络传输效率)
2.pipeline每次只能作用在一个redis节点上