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的应答。缓存
这里能够设想一下,若是客户端经过ACK,WIN=0(接收窗口)来控制服务端不能再发送数据,那么数据就会堆积在服务端socket发送缓冲区中,若是服务端socket发送缓冲区也满了,那么此时服务端调用write(socket)就会阻塞或者失败。服务器
既然提到了tcp/ip的滑动窗口概念,这里就简单总结下滑动窗口:网络
滑动窗口在TCP中的做用是提供TCP的可靠性和流控特性,滑动窗口可分为发送窗口和接收窗口,它们分别对应于发送缓冲区和接收缓冲区。发送窗口的大小是根据客户端接收缓冲区的大小而设定的(三次握手的目的是链接服务器指定端口,创建 TCP 链接,并同步链接双方的序列号和确认号,交换 TCP 窗口大小信息)。socket
发送窗口中包含的内容是已发送但还未收到Ack的数据和未发送但对端容许发送的数据。tcp
TCP接收缓冲区中包含应用为读取数据、已接收数据(已回复ACK)、待接收,其中待接收空间可称为接收窗口。性能
使用pipeline过程当中,要注意控制一次pipeline中的命令总大小,不能使响应结果撑爆socket接收缓冲区。这里咱们思考一个问题,还有没有其余方式提升pipeline的处理性能呢?理论上是有的,好比可使用数据压缩机制,进一步减少数据传输的总大小,不过这须要客户端和服务端提供解压缩机制,同时会耗费必定量服务器CPU。3d