redis pipeline服用指南

pipeline是Redis的一个提升吞吐量的机制,适用于多key读写场景,好比同时读取多个key的value,或者更新多个key的value。 工做过程当中发现挺多小伙伴都对pipeline多少有些了解,可是更深刻的理解或者说有哪些坑就不知道了,下面我们就一块儿分析下redis pipeline机制,揭开它的神秘面纱。redis

Redis自己是基于Request/Response协议(停等机制)的,正常状况下,客户端发送一个命令,等待Redis返回结果,Redis接收到命令,处理后响应。在这种状况下,若是同时须要执行大量的命令,那就是等待上一条命令应答后再执行,这中间不只仅多了RTT(Round Time Trip),并且还频繁调用系统IO,发送网络请求。为了提高效率,这时候pipeline出现了,它容许客户端能够一次发送多条命令,而不等待上一条命令执行的结果,这和网络的Nagel算法有点像(TCP_NODELAY选项)。 pipeline不只减小了RTT,同时也减小了IO调用次数(IO调用涉及到用户态到内核态之间的切换) 。算法

要支持Pipeline,其实既要服务端的支持,也要客户端支持。对于服务端来讲,所须要的是可以处理一个客户端经过同一个TCP链接发来的多个命令,能够理解为,这里将多个命令切分,和处理单个命令同样(以前老生常谈的黏包现象),Redis就是这样处理的。而客户端,则是要将多个命令缓存起来,缓冲区满了或者达到发送条件就发送出去,最后才处理Redis的应答。缓存

注意:Redis的Pipeline和Transaction(Redis事务)不一样,Transaction会存储客户端的命令,最后一次性执行,而Pipeline则是处理一条(批次),响应一条,从两者的不一样处理机制来看,Redis事务中命令的执行是原子的(注意,其中一部分命令出现错误后续命令会继续执行,这里的原子说的是命令执行是完整的,中间不会被其余Redis命令所打断),而pipeline中命令的执行不必定是原子的。可是这里却有一点不一样,就是pipeline机制中,客户端并不会调用read去读取socket里面的缓冲数据(除非已经发完pipeline中全部命令),这也就形成了,若是Redis应答的数据填满了该接收缓冲(SO_RECVBUF),那么客户端会经过ACK,WIN=0(接收窗口)来控制服务端不能再发送数据,那样子,数据就会缓冲在Redis的客户端应答缓冲区里面。因此须要 注意控制Pipeline的大小 。以下图:

这里能够设想一下,若是客户端经过ACK,WIN=0(接收窗口)来控制服务端不能再发送数据,那么数据就会堆积在服务端socket发送缓冲区中,若是服务端socket发送缓冲区也满了,那么此时服务端调用write(socket)就会阻塞或者失败。服务器

既然提到了tcp/ip的滑动窗口概念,这里就简单总结下滑动窗口:网络

滑动窗口在TCP中的做用是提供TCP的可靠性和流控特性,滑动窗口可分为发送窗口和接收窗口,它们分别对应于发送缓冲区和接收缓冲区。发送窗口的大小是根据客户端接收缓冲区的大小而设定的(三次握手的目的是链接服务器指定端口,创建 TCP 链接,并同步链接双方的序列号和确认号,交换 TCP 窗口大小信息)。socket

发送窗口中包含的内容是已发送但还未收到Ack的数据和未发送但对端容许发送的数据。tcp

TCP接收缓冲区中包含应用为读取数据、已接收数据(已回复ACK)、待接收,其中待接收空间可称为接收窗口。性能

使用pipeline过程当中,要注意控制一次pipeline中的命令总大小,不能使响应结果撑爆socket接收缓冲区。这里咱们思考一个问题,还有没有其余方式提升pipeline的处理性能呢?理论上是有的,好比可使用数据压缩机制,进一步减少数据传输的总大小,不过这须要客户端和服务端提供解压缩机制,同时会耗费必定量服务器CPU。3d

相关文章
相关标签/搜索