Redis(六)管道(Pipelining)
管道技术并不是Redis特有的,管道技术在计算机科学中有很多地方的应用。
来自wiki的解释:
In computing, a pipeline, also known as a data pipeline,[1] is a set of data processing elements connected in series, where the output of one element is the input of the next one. The elements of a pipeline are often executed in parallel or in time-sliced fashion. Some amount of buffer storage is often inserted between elements.
在计算机中,管道又叫做数据管道,是数据处理元件。一个元件的输出作为另一个元件的输入。管道中元素经常是并行或者是基于事件分片。在元素之间会插入缓冲区。
说白了就是传输计算元素。与计算机领域相关的管道非常多,其中平时应用开发中遇到的就是网络协议的HTTP pipelining。
HTTP Pipelining
HTTP pipelining is a technique in which multiple HTTP requests are sent on a single TCP connection without waiting for the corresponding responses.[1]
HTTP pipelining是一种技术,多个HTTP请求基于一个TCP连接以无等待匹配的响应的方式被发送。
HTTP中引入pipelining主要是为了提高性能。在一些高延迟的网络中,如果需要等待上一个HTTP请求的响应后再发送下一个请求,那么网络延迟势必是性能瓶颈之所在。pipelining为了解决这个问题,即流水线式发送HTTP请求,client不等待上一个请求的响应,只要server端按照请求的顺序返回响应即可。这样虽然无法从根本上解决网络延迟的问题,但是却可以减少request/response这种模式带来的环回时间。
Pipelining带来了以下的优势:
- 如上所述,减少了多个请求的整体环回时间,提高了性能
- 对于server端,能够在单位时间内接收到更多的请求,在server性能满足的前提下,提高了server端的吞吐量
同样万物平衡,Pipelining也有很多限制:
- 请求之间应该保证无依赖,后一个请求不能依赖前一个请求的响应结果。这种场景不适合使用pipelining
- 非幂等性请求不能使用pipelining(如post请求),同样的post请求会改变资源的状态,在使用pipelining技术中,会导致不幂等
下图引用wiki和《HTTP权威指南》中关于HTTP pipelining的描述:
参考
Pipelining
HTTP pipelining
《HTTP权威指南》
Redis-Pipelining
在看完pipelining,相信大家对管道(流水线)技术有一个初识。下面再来看下它是如何在Redis中被应用,为什么应用。
- Redis Pipelining介绍
- Redis Pipelining解决的问题
- Jedis中Pipelining的使用
- Jedis中的Pipleling的Benchmark
- Redis Pipelining在项目实战中的应用
一.Redis Pipelining介绍
Redis是是一种client-server的request/response的模式,Redis有单独的TCP Server。
- client发送请求请求到server端,然后需要阻塞等待server端的响应
- server端处理请求然后返回响应给client
即如上中介绍的HTTP的request/response一样。在这种模式中,数据包必须从client发送到server端,然后再从server端返回到client端,这个时间叫做RTT(Round Trip Time)。
假设Redis Server每秒能处理100k请求,但是RTT是250ms,这样Redis Server实际每秒只能处理4个请求,而且这种影响会随着网络延迟越大而逐渐加剧。所带来的直接影响:
- 阻塞客户端线程或进程,消耗资源,大量请求时无疑降低client性能
- 降低server端的吞吐量
为了解决该问题,需要一种client无等待响应的方式发送请求至server的模式,即Redis pipelining。
Redis pipelining使得client能够无等待响应的方式连续发送多条命令请求至Redis Server端,然后Server端按照请求顺序返回响应结果,类似:
client> set k0 v0;
client> set k1 v1;
client> set k2 v2;
server> ok
server> ok
server> ok
二.Redis Pipelining解决的问题
从以上的Redis pipelining介绍中可以看出,Redis pipelining降低了高延迟网络中,request/response方式带来的请求应答的环回时间消耗:
- 无序等待响应的方式发送请求,减少等待时间(特别在高延迟网络中)
- 一次性返回响应,减少多次响应的带来的时间消耗
更重要的一点是,在request/response的方式中,逐次发送请求至server端,server端每次都需要read/write,这里的read/write是systcall,涉及到内核态和用户态的切换,非常消耗系统资源。Redis pipelining的方式尽量减少了这种系统状态的切换开销。
三.Jedis中Pipelining的使用
Pipelining急需要Redis Server端的支持又需要Redis client的支持。client需要能够不获取响应的情况下发送多个命令,server端需要编排好响应以请求的顺序返回给客户端。
Redis的经典Client jedis是支持Pipelining的。使用方式可以分为两种,获取响应方式也可以分为两种。
1.使用pipelining方式:
- 直接使用pipelining
- 在事务中使用pipelining
2.获取响应方式:
- 同步,一次性获取所有请求的响应,以list方式返回
- 同步,在调用pipelining的操作时,指定返回的响应
关于测试的代码和pipelining的api使用详情可以戮
四.Jedis中的Pipleling的Benchmark
前面第二节中分析Pipelining就是解决网络延迟,提高吞吐量。那么在使用Pipelining的情况下,相对于不使用的情况下,性能是否提高了?提高多少?
一切都需要用数据来说话。下面分别跑下测试,比较下。Jedis的测试案例中有Benchmark模块,这里直接使用其Pipelining和GetSet的Benchmark的测试程序:
执行命令数 | ops(no pipelining/pipelining) |
---|---|
100 | 6666 ops/9090 ops |
100000 | 26870 ops/316455 ops |
1000000 | 28967 ops/422922 ops |
从以上的可以看出使用Pipelining的情况下大致能提高20倍的性能。
五.Redis Pipelining在项目实战中的应用
首先认识下Pipelining的特点:
- 批量流水线发送
- 一次返回相应的响应
两个特点决定了应用场景必须有以下特点:
- 由于是批量流水线发送,所以每个请求之间需要无状态,即后请求不依赖前请求的响应结果
- 由于一次返回响应,所以响应中可能会存在有些请求命令执行成功,有些失败。所以应用场景必须能够容忍数据处理错误或者数据丢失的风险,或者能够接受通过其他机制弥补丢失或者错误的数据方式
一般适用于批量缓存数据或者预加载缓存数据。因为不需要逐条发送缓存的数据,可以pipelining方式发送。因为是缓存数据,缓存的场景能够容忍某一些数据缓存失败,无非是没有命中,再次加载单条加载至缓存。
最近在做一个业务数据预警检查的项目,采用责任链模式,将需要预警检查的每条数据遍历责任链,完成数据一致性校验检查。责任链中每个检查器都是可配置生效失效,而且支持可扩展检查器。扩展性、可配置型较强,但是带来的问题即每条需要预警检查的数据遍历责任链检查器时,都需要重复的查询一些其他的表数据与配置。这里从而引入了巨大的磁盘I/O,产生性能瓶颈。
后来想如果,能将这些其他表的数据预加载进入缓存中,每次遍历需要预警检查的数据时,不从DB中查询获取,直接从缓存中获取即可。由于服务是集群的,所以需要使用分布式缓存且本地缓存容量有限。
这里最终采用懒加载的方式缓存其他表的数据或者配置,在预警检查第一条数据时,各个检查器将其他表的数据或者配置加载到缓存中,同时采用pipelining模式缓存到Redis中。
这样下条预警数据的遍历检查器时,每个检查器从缓存中获取其他表的数据或者配置即可。大幅度减少DB带来的I/O,突破性能瓶颈。
Redis(六)管道(Pipelining)的更多相关文章
- 第三百零一节,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六(管道)
管道 为什么使用管道? Redis是一个TCP服务器,支持请求/响应协议. 在Redis中,请求通过以下步骤完成: 客户端向服务器发送查询,并从套接字读取,通常以阻塞的方式,用于服务器响应. 服务器处 ...
- REDIS 六. 修复方案
六. 修复方案 6.1 禁止一些高危命令(重启redis才能生效) 修改 redis.conf 文件,禁用远程修改 DB 文件地址 rename-command FLUSHALL "&quo ...
- redis使用管道pipeline提升批量操作性能(php演示)
Redis是一个TCP服务器,支持请求/响应协议. 在Redis中,请求通过以下步骤完成: 客户端向服务器发送查询,并从套接字读取,通常以阻塞的方式,用于服务器响应. 服务器处理命令并将响应发送回客户 ...
- python学习之-- redis模块管道/订阅发布
redis 模块操作剩余其他常用操作 delete(*names):删除任意的数据类型exists(name):检测redis的name是否存在keys(pattern='*'):根据模型获取redi ...
- redis之管道
Redis 的消息交互当我们使用客户端对 Redis 进行一次操作时,如下图所示,客户端将请求传送给服务器,服务器处理完毕后,再将响应回复给客户端.这要花费一个网络数据包来回的时间. 如果连续执行多条 ...
- 高可用Redis(六):瑞士军刀之bitmap,HyperLoglog和GEO
1.bitmap位图 1.1 bitmap位图的概念 首先来看一个例子,字符串big, 字母b的ASCII码为98,转换成二进制为 01100010 字母i的ASCII码为105,转换成二进制为 01 ...
- Linux网络编程学习(六) ----- 管道(第四章)
1.管道的定义 管道就是将一个程序的输出和另外一个程序的输入连接起来的单向通道,比如命令: ls -l|more,就建立了一个管道,获取ls -l的输出作为more的输入,数据就沿着管道从管道的左边流 ...
随机推荐
- iOS tableView侧滑删除的第三方控件
(到我的文件中,下载“tableview中cell测滑删除的第三方控件”),使用方法如下: 在tableView中的.m中,设置cell的方法上,事例代码如下,其中,EaseConversationC ...
- MyCat教程六:全局序列号-全局主键的自增长
前面我们介绍了MyCat的分库分表操作,那么同一张表中的数据会被保存在不同的数据库中,那么这就涉及到了主键维护的问题,此时肯定不能使用单个数据库中id自增的方式来处理了,这时我们就可以通过MyCa ...
- python 类 专有方法
__init__ : 构造函数,在生成对象时调用 __del__ : 析构函数,释放对象时使用 __repr__ : 打印,转换 __setitem__ : 按照索引赋值 __getitem__: 按 ...
- Rust中的泛型
go没有的,rust有呢~~ fn largest<T: PartialOrd + Copy>(list: &[T]) -> T { let mut largest = li ...
- 模仿51cto搜索框
做这个demo遇见的问题 1==>input type=submit有默认样式 padding:1px 6px所以将他去除 2==>input submit有默认样式 去除默认边框 bor ...
- git的使用(二)
GITHUB 简介 github可以是全世界最大的同性交友网站,其实就是和百度云一个性质. gitHub于2008年4月10日正式上线,除了git代码仓库托管及基本的 Web管理界面以外,还提供了订阅 ...
- 杂项-FLAG
题目 最低位隐写 50 4B 03 04 压缩格式zip的文件头 save bin 保存成zip格式 解压(WinRAR不能正常解压) 然后用vim打开(winhex也可以) hctf{dd0gf4c ...
- window.devicePixelRatio ,px,rem
window属性:devicePixelRatio 设备像素比 https://www.w3cschool.cn/fetch_api/fetch_api-atvq2nma.html devicePix ...
- c:forTokens标签循环输出
对带有相同符合格式内容进行分割输出,例如,varstr="1,2,3,4,5,6"; c:forTokens属性说明表 引用 varStatus,它们描述了迭代的当前状态,如下这些 ...
- Taro/JS/H5/小程序:纯前端解决小程序微信支付统一下单和调起支付
这个文章不会说具体0到1的代码流程,我会着重讲几个问题的解决 准备以下依赖 "md5": "^2.2.1", "xml-js": " ...