编者注:pipeline是Redis的一个提高吞吐量的机制,适用于多key读写场景,比如同时读取多个key的value,或者更新多个key的value。工作过程中发现挺多小伙伴都对pipeline多少有些了解,但是更深入的理解或者说有哪些坑就不知道了,下面咱们就一起分析下redis pipeline机制,揭开它的神秘面纱。

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 窗口大小信息)。

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


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

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

欢迎小伙伴关注【TopCoder】阅读更多精彩好文。

如何用好redis pipeline的更多相关文章

  1. redis pipeline

    redis pipeline 简而言之就是把多个redis命令打包,一起发送给redis server,并且一起返回结果,减少客户端和服务器之间的多次“折返跑”

  2. 【spring boot】spring boot 基于redis pipeline 管道,批量操作redis命令

    spring boot 2.x 使用RedisTemplate 操作 =================================== 1.pom.xml <!--spring2.0集成r ...

  3. laravel中redis pipeline用法说明

    $res = Redis::pipeline(function($pipe) use($params) { for ($i = 0; $i < 1000; $i++) { $pipe->g ...

  4. redis 学习(11)-- redis pipeline

    redis pipeline 什么是流水线(pipeline) 首先来看 redis 执行一次操作所需要的时间: 1 次时间 = 1 次网络时间 + 1次命令时间 执行 n 次就需要: n 次时间 = ...

  5. 等待 Redis 应答 Redis pipeline It's not just a matter of RTT

    小结: 1.When pipelining is used, many commands are usually read with a single read() system call, and ...

  6. 说说 Redis pipeline

    更多技术文章,请关注我的个人博客 www.immaxfang.com 和小公众号 Max的学习札记. Redis 客户端和服务端之间是采用 TCP 协议进行通信的,是基于 Request/Respon ...

  7. (7)redis pipeline

    redis是一个cs模式的tcp server,使用和http类似的请求响应协议.一个client可以通过一个socket连接发起多个请求命令.每个请求命令发出后client通常 会阻塞并等待redi ...

  8. Redis pipeline and list

    Redis Redis 是一个开源的基于内存的数据结构存储器.通常可作为数据库,缓存和消息中介.它支持的数据结构有:字符串.哈希表.列表.集合.支持范围查询的有序集合.位图.hyperloglogs和 ...

  9. Redis Pipeline原理分析

    转载请注明出处:http://www.cnblogs.com/jabnih/ 1. 基本原理 1.1 为什么会出现Pipeline Redis本身是基于Request/Response协议的,正常情况 ...

随机推荐

  1. java8 函数接口

    [前言] java8新特性 java8 Optional使用总结 java8 lambda表达式 Java 8 时间日期使用 1.函数式接口新特性 java8中引入了函数式接口新特性,使用@Funct ...

  2. Quartz系列(一):基础介绍

    新建一个.NET Core控制台项目,NuGet引用Quartz引用. class Program { static void Main(string[] args) { var task = Tas ...

  3. python 对excel进行截图

    工作中需要对excel的单元格区域进行截图,以前是调用vba进行(走了很多弯路,虽然能实现,但比较low),后来逐步发现python的win32com与vba师出同门,很多方法操作都是类似的. 可以对 ...

  4. JPG和PNG特性分析及适用范围

    个人博客: http://mcchen.club JPG的特性   ----有损压缩 1.支持摄影图像或写实图像的高级压缩,并且可利用压缩比例控制图像文件大小. 2.有损压缩会使图像数据质量下降,并且 ...

  5. 【TencentOS tiny】深度源码分析(7)——事件

    引言 大家在裸机编程中很可能经常用到flag这种变量,用来标志一下某个事件的发生,然后在循环中判断这些标志是否发生,如果是等待多个事件的话,还可能会if((xxx_flag)&&(xx ...

  6. python urllib2实现http GET PUT DELETE POST的方法

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/3/11 下午8:33 # @Author : liubing # @File ...

  7. Python Flask高级编程之从0到1开发《鱼书》精品项目 ☝☝☝

    Python Flask高级编程之从0到1开发<鱼书>精品项目 ☝☝☝ 一 .安装环境我们使用 flask web框架,并用 sqlalchemy来做数据库映射,并使用 migrate做数 ...

  8. 就个人银行账户管理程序谈谈C++和Java的异同

    4_9 同: Java和C++都是面向对象的语言.都有数据成员,方法,访问权限的概念. 异: 访问权限上,非private时Java的默认访问权限是包.而C++的默认访问权限是private.Java ...

  9. Eclipse 创建 Maven 项目

    本人也是新手小白,在创建 Maven 项目的时候几乎踩完了所有的坑.特此总结如下: 1.咱先选中 File -> New -> Maven Project 2.然后如下图    在这里说明 ...

  10. PHP会话机制---session的基本使用

    登录网站后,在每个网页都能拿到用户信息 (1) 使用超链接传递用户名,这样太繁琐了,不建议使用 . (2) 使用数据库,每打开一个页面都查询一次用户信息表,这样网页加载速度变慢,用户体验变差. (3) ...