Redis使用的是客户端-服务器(C-S)模型和请求/响应协议的TCP服务器。这意味着通常情况下一个请求会遵循以下步骤:
- 第一步:客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
- 第二步:服务端处理命令,并将结果返回给客户端。
视频讲解如下:
Redis执行的过程如图1所示:
由于网络开销延迟,就算Redis Server端有很强的处理能力,也会由于收到的客户端消息少,而造成吞吐量小。管道PipeLine可以一次性发送多条命令并在执行完后一次性将结果返回。管道PipeLine通过减少客户端与Redis服务器端的通信次数来实现降低往返延时时间,而且管道PipeLine 实现的原理是队列,而队列的原理是时先进先出,这样就保证数据的顺序性。管道PipeLine的工作过程如图2所示。
图2中的客户端可以将三个命令放到一个TCP报文一起发送;而Redis服务器端则可以将三条命令的处理结果放到一个TCP报文返回。下面通过Java代码来测试普通的Redis操作和Redis PipeLine操作在性能上的差别。
import org.junit.Test; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; public class TestRedisPipeLine { public void testNormalCommand() { Jedis client = new Jedis("192.168.79.11", 6379); long start = System.currentTimeMillis(); for(int i=0;i<10000;i++) { client.set("key" + i, "value"+i); } long end = System.currentTimeMillis(); client.close(); System.out.println("使用普通命令插入1万条数据的执行时间为:"+ (end - start)); } public void testPipeLineCommand() { Jedis client = new Jedis("192.168.79.11", 6379); Pipeline pl = client.pipelined(); long start = System.currentTimeMillis(); for(int i=0;i<10000;i++) { pl.set("key" + i, "value"+i); } pl.sync(); long end = System.currentTimeMillis(); client.close(); System.out.println("使用管道命令插入1万条数据的执行时间为:"+ (end - start)); } }
视频讲解如下:
分别运行testNormalCommand()和testPipeLineCommand()方法输出的结果如下:
- 使用普通命令插入1万条数据的执行时间为:1147
- 使用管道命令插入1万条数据的执行时间为:92
提示:管道PipeLine在某些场景下非常有用,比如有多个命令需要被"及时的"提交,而且他们对相应结果没有互相依赖,对结果响应也无需立即获得,那么管道PipeLine就可以充当这种"批处理"的工具;而且在一定程度上,可以较大的提升性能,性能提升的原因主要是TCP连接中减少了"交互往返"的时间。