今天分享一个Redis的小功能,Pipeline(流水线)。Pipeline能够将一组Redis命令组装起来,通过一次请求发给Redis服务端,Redis服务端执行完这些命令之后再将这些命令的结果一次性返回给客户端。
Redis执行一条命令分为四个步骤:
- 发送命令
- 命令排队
- 命令执行
- 返回结果
其中发送命令和返回结果两步的时间和称之为Rount Trip Time(RTT,往返时间)。假设我们以工要向Redis服务端发送 n 条消息,使用Pipeline就能帮我们节省 n - 1 次RTT时间。
如果Redis客户端在上海,服务端在北京,两地直线距离1300公里,假设光纤为光速的 2/3,那么一次RTT的时间为 1300 * 2 / (300000 * 2 / 3) = 13 毫秒,而Redis处理命令的时间通常在微妙级别,所以有Redis的性能瓶颈在网络这么一种说法。
所以在网络延迟比较大的场景下使用Pipeline来处理多条消息,可以大幅度减少请求响应总时间。
Redis的Pipeline功能需要客户端的支持,下面有一段Jedis客户端使用Pipeline功能的代码:
public static void testPipeline(){
//生成pipeline对象
Pipeline pipelined = jedis.pipelined();
//向pipeline对象中添加命令
pipelined.set("hello", "world");
pipelined.incr("incrnum");
pipelined.get("hello");
//调用syncAndReturnAll方法会执行pipeline中的命令,并且返回结果
//pipelined.sync()会执行pipeline中的命令,不返回结果
List<Object> list = pipelined.syncAndReturnAll();
System.out.println(list);
}
Redis原生也提供了一些批处理命令,如mget、mset等,也能减少多条命令的RTT时间,但是这些原生的批处理命令只能提供单一的命令,不像Pipeline命令那样可以处理很多不同类型的命令。
Pipeline命令虽然好用,但使用的时候还是要注意一些问题的:
- Pipeline是非原子的
- 如果一次组装的Pipeline数据量过大,会增加客户端的等待时间,也会造成Redis服务端的阻塞,可以考虑将一次数据量过大的Pipeline命令拆分成多个小的Pipeline命令来完成。
小功能大用处,一天一个小知识点,学到就是赚到。