1 Pipeline概念
Redis客户端执行一条命令的流程如下
- 发送命令
- 命令排队
- 命令执行
- 返回结果
其中步骤1+步骤4所使用的时间称为往返时间(Round trip time) RTT
Redis提供了部分批量操作的命令,例如mget、mset,但是还有很多操作是不能批量进行的,例如要执行n次hgetall 或者n次del操作,那么需要消耗n次RTT。在比较极端的条件下,例如机房比较远,那么1s能执行的客户端命令是极其有限的,这和Redis的高并发高吞吐量背道而驰
Pipeline就能改善此类问题,Redis pipeline将多条命令组装,一次性发给Redis服务端,命令执行完成后再一次性返回结果,原本n条命令需要n*RTT时间(假设每次发送的RTT相同),通过Pipeline发送后,只需要一次RTT时间,
2 Jedis 使用Pipeline
下面使用Jave版的Jedis客户端演示使用Pipeline进行批量删除操作
// 批量删除
void batchDel(String...keys){
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
Pipeline pipeline = jedis.pipelined();
for(String key : keys){
jedis.del(key);
}
pipeline.sync();
}finally {
if(jedis != null){
jedis.close();
}
}
}
// 批量删除并返回结果
void batchDelWithResult(String...keys){
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
Pipeline pipeline = jedis.pipelined();
for(String key : keys){
jedis.del(key);
}
List<Object> result = pipeline.syncAndReturnAll();
// 如果是成功删除两个key,输出结果为
// ok
// ok
for (Object object : result) {
System.out.println(object);
}
}finally {
if(jedis != null){
jedis.close();
}
}
}
3 tips
Pipeline虽然好用,但是每次Pipeline组装的命令个数不能没有节制,否则一次组装Pipeline数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分成多次较小的Pipeline来完成。
RedisCluster对Pipeline的支持有所限制,Pipeline执行的所有命令key值通过hash函数映射到的slot值必须相同,不然Pipeline不能执行