redis pipeline
什么是流水线(pipeline)
首先来看 redis 执行一次操作所需要的时间:
1 次时间 = 1 次网络时间 + 1次命令时间
执行 n 次就需要:
n 次时间 = n 次网络时间 + n 次命令时间
所以可以看到,如果执行 n 次的话(比如 n 次 set 操作),时间开销是非常大的。
由于命令时间非常短,影响时间开销的主要是网络时间,所以我们可以把一组命令打包,然后一次发送过去。这样的话,时间开销就变为:
1 次 pipeline(n条命令) = 1 次网络时间 + n 次命令时间
pipeline 的好处
- 省略由于单线程导致的命令排队时间,一次命令的消耗时间=一次网络时间 + 命令执行时间
- 比起命令执行时间,网络时间很可能成为系统的瓶颈
- pipeline的作用是将一批命令进行打包,然后发送给服务器,服务器执行完按顺序打包返回。
- 通过pipeline,一次pipeline(n条命令)=一次网络时间 + n次命令时间
命令 | N个命令操作 | 1次pipeline(n个命令) |
---|---|---|
时间 | n次网络+n次命令 | 1次网络+n次命令 |
数据量 | 1条命令 | n条命令 |
pipeline VS M 操作(mget、mset)
之前我们讲过 M 操作,也是类似 pipeline,将多个命令一次执行,一次发送出去,节省网络时间。对比如下:
- M操作在Redis队列中是一个原子操作,pipeline不是原子操作
- pipeline与M操作都会将数据顺序的传送顺序地返回(redis 单线程)
- M 操作一个命令对应多个键值对,而Pipeline是多条命令
pipeline注意事项
- 每次pipeline携带数量不推荐过大,否则会影响网络性能
- pipeline每次只能作用在一个Redis节点上
pipeline-Jedis使用
Maven 依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
代码如下
//没有使用pipieline的情况下
public void testWithoutPipeline() {
Jedis jedis = new Jedis("127.0.0.1" , 6379);
for(int i = 1 ; i <= 10000 ; i++ ) {
jedis.hset("hashKey-" + i , "field-" + i , "value-" + i);
}
}
//使用pipeline的情况下
public void testPipeline() {
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 ; i < (i+1) * 100 ; j++ ) {
pipeline.hset("hashKey-" + j , "field-" + j , "value-" + j);
}
pipeline.syncAndReturnAll();
}
}