背景
redis客户端执行一条命令分4个过程:
发送命令 -> 命令排队 -> 命令执行 -> 返回结果
这个过程称为Round trip time
(简称RTT
, 往返时间),mget
mset
有效节约了RTT,但大部分命令(如hgetall
,并没有mhgetall
)不支持批量操作,需要消耗N次RTT
,这个时候需要pipeline
来解决这个问题
Jedis测试
Jedis jedis = new Jedis();
long start = System.currentTimeMillis();
Pipeline pipelined = jedis.pipelined();
for (int i = 0; i < 10000; i++) {
pipelined.set("key:" + i, "value" + i);
}
pipelined.sync();
long pause = System.currentTimeMillis();
System.out.println((pause - start) + "ms");
for (int i = 0; i < 10000; i++) {
jedis.set("key:" + (i << 1), "value" + i);
}
long end = System.currentTimeMillis();
System.out.println((end - pause) + "ms");
结果大概是
73ms
279ms
总结
-
为什么要pipeline?
避免多条命令发送造成的性能浪费,尤其是客户端与服务端的网络延迟越大,pipeline优势越明显。
-
pipeline是原子性的吗?
不是,但
mget
、mset
是。 -
与原生批命令的对比?
-
原生批命令是原子性,pipeline是非原子性
-
原生批命令一命令多个key, 但pipeline支持多命令(存在事务),非原子性
-
原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成
-