背景以及概念:

     原始查询,我们主要通过调用redis客户端执行单get,set操作,每次查询都将新建连接,实际项目的耗时主要来源于网络耗时,当数据较少,单次查询/修改性能影响不明显,当命令达W级别,单命令操作耗时影响很大;redis提供了管道技术,正好可以弥补这个缺点,

     redis-pipeline 技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。

特点: 有效的减少了RTT和redis连接数,同时也减少了IO调用次数(IO调用涉及到用户态到内核态之间的切换)。

     ****

    内核态用户态:

                          https://zhuanlan.zhihu.com/p/69554144

    ****

    pipeline并未保证原子性。即同一个pipeline中的命令在redis-server被执行的顺序可以保证,但不保证其中不会穿插其余的客户端请求的命令。 可以通过redis的slowlog查看命令的执行顺序,以验证此特点

   每次Pipeline组装的命令个数不能没有节制,否则一次组装Pipeline数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分成多次较小的Pipeline来完成。

    使用管道发送命令时,服务器将被迫回复一个队列答复,占用很多内存。所以,如果你需要发送大量的命令,最好是把他们按照合理数量分批次的处理。 例如10K的命令,读回复,然后再发送另一个10k的命令,等等。这样速度几乎是相同的,但是在回复这10k命令队列需要非常大量的内存用来组织返回数据内容。

redis_pipeline模型

redis output网络带宽比input高 redis pipeline性能_数据

 

     client首先把执行的命令存放在缓冲区(client-buffer),最后统一执行,但是有一种情况是,缓冲区(client-buffer)的大小是有限制的,比如Jedis,限制为8192,超过了,则刷缓存,发送请求到Redis,但是jedis不会去处理Redis的应答,如上图所示那样。

     Redis的Pipeline和Transaction(Multi)不同,Transaction会存储客户端的命令,最后一次性执行,而Pipeline则是处理一条响应一条。 但是这里却有一点,就是客户端会并不会调用read去读取socket里面的缓冲数据。 这也就造就了,如果Redis应答的数据填满了该接收缓冲(SO_RECVBUF),那么客户端会通过ACK,WIN=0(接收窗口)来控制服务端不能再发送数据, 那样子,数据就会缓冲在Redis的客户端应答列表里面。所以需要注意控制Pipeline的大小

     例如图中的,value1,value2,value3假设client接收到了此response,(假设)并保存在client-receive-buffer(客户端 接收缓冲区),且刚好占满client-receive-buffer。

    但是,client并不会去read,且 client-receive-buffer 被占满,client会通过 ack,win=0通知redis-server不要再发送响应数据。因此要控制pipeline的大小。

 

    核心点:pipeline管道模式,较少了ttl,io切换的耗时,使批量命令的执行相对提高了N倍。

   细节点:server对pipeline的命令结果进行缓存处理,会消耗很多内存,同时client执行命令后,结果会缓存在client-revice-buffer中,如果缓存满了,通知server停止发送数据,因此要控制好每次pipeline的大小,保持效率最高;

    常见误区:pipeline每次命令执行多少对于速度不会影响,因为pipeline是长连接的,因此10k命令分为100此0.1k命令并不会造成速度的减慢。

实际项目优化案列:

实际项目耗时:

client访问trpc服务:server查询redis(pipeline方式),1w级别耗时1.17s(包括浏览器与sever的2RTT,server与redis的2RTT)以及linux的IO,线程操作;

redis output网络带宽比input高 redis pipeline性能_redis_02

 

 

相比下,原始client模型,单次访问,单次回复的模式,耗时11.7s

 

redis output网络带宽比input高 redis pipeline性能_redis_03

优化:相比10倍,随着数据的增多,优化效率更加明显;

具体代码没有贴出,涉及私密;

piple通道的使用可以参考官网的文档,进行编写;