redis之管道
Redis 的消息交互
当我们使用客户端对 Redis 进行一次操作时,如下图所示,客户端将请求传送给服务
器,服务器处理完毕后,再将响应回复给客户端。这要花费一个网络数据包来回的时间。
如果连续执行多条指令,那就会花费多个网络数据包来回的时间。如下图所示。
回到客户端代码层面,客户端是经历了写-读-写-读四个操作才完整地执行了两条指令。
现在如果我们调整读写顺序,改成写—写-读-读,这两个指令同样可以正常完成。
两个连续的写操作和两个连续的读操作总共只会花费一次网络来回,就好比连续的 write
操作合并了,连续的 read 操作也合并了一样。
这便是管道操作的本质,服务器根本没有任何区别对待,还是收到一条消息,执行一条
消息,回复一条消息的正常的流程。客户端通过对管道中的指令列表改变读写顺序就可以大
幅节省 IO 时间。管道中指令越多,效果越好。
管道压力测试
接下来我们实践一下管道的力量。
Redis 自带了一个压力测试工具 redis-benchmark,使用这个工具就可以进行管道测试。
首先我们对一个普通的 set 指令进行压测,QPS 大约 5w/s。
> redis-benchmark -t set -q
SET: 51975.05 requests per second
我们加入管道选项-P 参数,它表示单个管道内并行的请求数量,看下面 P=2,QPS 达到
了 9w/s。
> redis-benchmark -t set -P 2 -q
SET: 91240.88 requests per second
再看看 P=3,QPS 达到了 10w/s。
SET: 102354.15 requests per second
但如果再继续提升 P 参数,发现 QPS 已经上不去了。这是为什么呢?
因为这里 CPU 处理能力已经达到了瓶颈,Redis 的单线程 CPU 已经飙到了 100%,所
以无法再继续提升了。
深入理解管道本质
接下来我们深入分析一个请求交互的流程,真实的情况是它很复杂,因为要经过网络协
议栈,这个就得深入内核了。
上图就是一个完整的请求交互流程图。我用文字来仔细描述一遍:
1、客户端进程调用 write 将消息写到操作系统内核为套接字分配的发送缓冲 send
buffer。
2、客户端操作系统内核将发送缓冲的内容发送到网卡,网卡硬件将数据通过「网际路
由」送到服务器的网卡。
3、服务器操作系统内核将网卡的数据放到内核为套接字分配的接收缓冲 recv buffer。
4、服务器进程调用 read 从接收缓冲中取出消息进行处理。
5、服务器进程调用 write 将响应消息写到内核为套接字分配的发送缓冲 send buffer。
6、服务器操作系统内核将发送缓冲的内容发送到网卡,网卡硬件将数据通过「网际路
由」送到客户端的网卡。
7、客户端操作系统内核将网卡的数据放到内核为套接字分配的接收缓冲 recv buffer。
8、客户端进程调用 read 从接收缓冲中取出消息返回给上层业务逻辑进行处理。
9、结束。
其中步骤 5~8 和 1~4 是一样的,只不过方向是反过来的,一个是请求,一个是响应。
我们开始以为 write 操作是要等到对方收到消息才会返回,但实际上不是这样的。write
操作只负责将数据写到本地操作系统内核的发送缓冲然后就返回了。剩下的事交给操作系统
内核异步将数据送到目标机器。但是如果发送缓冲满了,那么就需要等待缓冲空出空闲空间
来,这个就是写操作 IO 操作的真正耗时。
我们开始以为 read 操作是从目标机器拉取数据,但实际上不是这样的。read 操作只负
责将数据从本地操作系统内核的接收缓冲中取出来就了事了。但是如果缓冲是空的,那么就
需要等待数据到来,这个就是读操作 IO 操作的真正耗时。
所以对于 value = redis.get(key)这样一个简单的请求来说,write 操作几乎没有耗时,直接
写到发送缓冲就返回,而 read 就会比较耗时了,因为它要等待消息经过网络路由到目标机器
处理后的响应消息,再回送到当前的内核读缓冲才可以返回。这才是一个网络来回的真正开
销。
而对于管道来说,连续的 write 操作根本就没有耗时,之后第一个 read 操作会等待一个
网络的来回开销,然后所有的响应消息就都已经回送到内核的读缓冲了,后续的 read 操作
直接就可以从缓冲拿到结果,瞬间就返回了。
redis之管道的更多相关文章
- 第三百零一节,python操作redis缓存-管道、发布订阅
python操作redis缓存-管道.发布订阅 一.管道 redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pi ...
- 【spring boot】spring boot 基于redis pipeline 管道,批量操作redis命令
spring boot 2.x 使用RedisTemplate 操作 =================================== 1.pom.xml <!--spring2.0集成r ...
- redis使用管道pipeline提升批量操作性能(php演示)
Redis是一个TCP服务器,支持请求/响应协议. 在Redis中,请求通过以下步骤完成: 客户端向服务器发送查询,并从套接字读取,通常以阻塞的方式,用于服务器响应. 服务器处理命令并将响应发送回客户 ...
- python学习之-- redis模块管道/订阅发布
redis 模块操作剩余其他常用操作 delete(*names):删除任意的数据类型exists(name):检测redis的name是否存在keys(pattern='*'):根据模型获取redi ...
- redis 使用管道提升写入的性能[pipeline]
看了手册的都知道multi这个命令的作用就好比是mysql的事务的功能,但是大家都知道事务吗,就是在操作的过程中,把整个操作当作一个原子来处理,避免由于中途出错而导致最后产生的数据不一致,而产生BUG ...
- 5. redis管道, 发布订阅, 模拟队列
一. 发布订阅 #订阅scribe 127.0.0.1:6379> SUBSCRIBE "channel_1" Reading messages... (press Ctrl ...
- Redis进阶实践之十八 使用管道模式加速Redis查询
一.引言 学习redis 也有一段时间了,该接触的也差不多了.后来有一天,以为同事问我,如何向redis中批量的增加数据,肯定是大批量的,为了这主题,我从新找起了解决方案.目前 ...
- redis学习(六)redis管道
redis管道 1.redis管道介绍 redis采用的是CS架构,客户端与服务器端通过tcp协议进行连接通信,因此无论是发出请求还是接收响应,都必须经过网络传输.在tcp连接过程中,客户端和服务器端 ...
- Redis管道传输
Redis是一个TCP服务器,并支持请求/响应协议.redis的一个请求完成需要下面的步骤: 客户端发送一个查询到服务器,并从套接字中读取,通常在封闭的方式,对服务器的响应. 服务器处理命令并将响应返 ...
随机推荐
- [Leetcode] 第334题 递增的三元子序列
一.题目描述 给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列. 数学表达式如下: 如果存在这样的 i, j, k, 且满足 0 ≤ i < j < k ≤ n-1, ...
- 神奇的互换身体术--java的类型擦除
故事背景 <互换身体>是由环球影业发行的喜剧电影,于2011年8月5日在美国上映.该片由大卫·道金执导,瑞安·雷诺兹.杰森·贝特曼.奥利维亚·王尔德等主演.该片讲述了一位居家好男人和一位蜂 ...
- class命名归类
常见class关键词: 布局类:header, footer, container, main, content, aside, page, section 包裹类:wrap, inner 区块类:r ...
- jupyter编辑快捷键
Jupyter笔记本有两种不同的键盘输入模式. 编辑模式允许您将代码或文本输入到一个单元格中,并通过一个绿色的单元格来表示 命令模式将键盘与笔记本级命令绑定在一起,并通过一个灰色的单元格边界显示,该边 ...
- Hadoop源代码点滴-基础概念
大数据特征:volume(数量).variety(多样性).velocity(产生的速度) 大数据特征:多.乱.快.杂 数据的来源:业务数据.日志.管理文档(OCR).互联网.物联网.外购
- linux 的vi/vim消除查找到的高亮字符串
方法如下: 在Vi里面如果要搜索某个关键字,只要键入/xxx就可以了,比如,要搜索一个函数,就键入/snprintf 然后回车,一个文件中,所有出现这个字样的地方都会被高亮显示.按n键,就可以自动把光 ...
- react redux 二次开发流程
在一个大项目中如何引入redux及其相关技术栈(react-redux redux-thunk redux-immutable ),已经成为react前端工程师不可或缺的技能,下面通过实现一个简单的t ...
- CentOS系统查看软件安装路径
Linux系统一般都是命令行界面,对于安装的软件也是通过命令安装的.对于软件包更新和卸载等有时候需要查看检查是否有改软件,软件安装存储的路径对于修改配置文件等是必要的.那么怎么查看软件安装路径呢?小编 ...
- 01 python安装与初识
一.简要概述 python学习时设计要大于开发. 二.编程语言 1.分类 编程语言分为高级语言和低级语言.高级语言如python.c#,Java.PHP等,低级语言(基础语言)如C.汇编语言. 2.机 ...
- 从 JVM 视角看看 Java 守护线程
Java 多线程系列第 7 篇. 这篇我们来讲讲线程的另一个特性:守护线程 or 用户线程? 我们先来看看 Thread.setDaemon() 方法的注释,如下所示. Marks this thre ...