Redis之管道

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis之管道

pipeline

下面是使用管道与不使用管道对redis set 6000条数据的效果,可以看到,使用管道技术用了不到1秒的时间,而不使用则耗费了4秒左右的时间。

image.png

源码地址:https://github.com/qiaomengnan16/redis-demo/tree/main/redis-pipeline

客户端与服务端消息交互过程

当客户端与Redis服务端进行交互时,客户端先发送指令,服务端处理完毕后返回结果,客户端读取到结果,此次操作结束,花费了一个网络数据包来回的时间。

image.png

如果连续执行多条指令,就花费了多个网络数据包来回的时间,

image.png

从客户端角度来看,两次请求是经过 写 -> 读,写 -> 读,四次操作执行完成的,写就是写入指令,读就是读取返回结果,读是要等待服务器响应的,这中间会经历一点耗时,例如第一次读耗时0.3秒,第二次读又耗时0.3秒,加起来就是0.6秒了。

image.png

改变交互过程

如果我们 set x1 1 , set x2 2,执行这两个指令存两个值,显然这两次操作并不相关,可以将这两个set指令一起发送过去,再读取返回值,省去中间一次读返回值的阻塞耗时,即调整读写顺序,将 写 -> 读,写 -> 读 的顺序改为 写写读读,

image.png

两次连续的写操作和连续的读操作只会花费一次网络来回的时间,连续的写操作被合并成一个,连续的读操作也被合并成一个,即读等待时间只花费0.3秒,redis的管道其实就是改变了写读的顺序使的速度变得更快。

服务器

image.png

原理

通过改变写读的顺序就可以让速度大幅度提升,根本原因是减少多个网络来回的开销

image.png

上图是发起一次完整的操作过程,步骤如下:

  1. 客户端调用 wirte 将消息写到操作系统内核为套接字分配的发送缓冲区 send buffer 中。
  2. 客户端操作系统内核将缓冲内容发送到网卡,网卡将数据发送到服务器端的网卡中。
  3. 服务器操作系统内核将网卡中的数据放到内核为套接字分配的接收缓冲区 recv buffer 中。
  4. 服务器通过调用 read 从接收缓冲区中取出消息进行处理。
  5. 服务器调用 wirte 将响应消息写到内核为套接字分配的发送缓冲区 send buffer 中。
  6. 服务器操作系统内核将缓冲区内容发送到网卡,网卡再将数据发送到客户端的网卡中。
  7. 客户端操作系统内核将网卡中的数据放到内核为套接字准备的接收缓冲区 recv buffer中。
  8. 客户端进程调用 read 从接收缓冲区中取出消息返回给上层业务逻辑进行处理。
  9. 结束。

步骤5、8与1、4是一样的,只是方向不同,一个是请求,一个是响应。

客户端的write操作将数据写入到操作系统内核的缓冲区中后就立刻返回,而不是等待发送到服务端才返回,剩下的事情由操作系统内核异步将数据发送到服务端,

如果发送缓冲区满了,那么write操作就需要等待缓冲区空闲出来,这是wirte的耗时时间,如果缓冲区没有满的话,返回速度是非常快的,随后就可以进行下一个写操作,

客户端的read操作负责从本地操作系统内核的接收缓冲区中读取数据,而不是从服务端拉取数据,如果服务端响应的很快,read操作就可以很快的读到数据,

如果接收缓冲区中没有数据,那么read就需要进行等待数据的来临,读取结束后返回,

对于管道的连续写和连续读来说,连续write操作基本等于是没有耗时的,只要缓冲区不满,就可以一直写,而read是等待服务端的数据响应,

响应过来的数据就是之前所有的操作结果响应,由此可以看出管道的快速本质在于客户端通过改变读写的顺序获得了巨大的性能提升。

适合场景

当Redis的多次操作毫不相关时,即后一个指令不依赖于上一个指令的执行结果,则可以使用管道进行处理,例如开篇的for循环set值,如果只是使用普通的set指令的话,接口限制时间如果是3秒,那就会因为redis大量的写读等待导致接口超时,

由于每次set操作都是不相干的,所以放心的用管道去做加速处理,相反如果后续的指令需要依赖前面的指令结果,则不适合用管道去做 (管道也是支持脚本的,可以在管道中发送一些脚本做依赖逻辑处理) ,从这种角度看,pipeline和批处理也比较相似。

编码时请注意,pipeline期间,管道将独占连接connection,不能进行其他非pipeline的操作,否则将会出错,如果需要做其他的处理, 需要使用新的 connection,和管道使用中的连接进行隔离,

同时需要注意,redis在处理完所有命令前,会将响应结果缓存在server端,缓存的越多,对内存的占用也会越多。

管道压力测试

redis自带一个压力测试工具 redis-benchmark,借此可以对管道进行测试,试试管道的威力。

下面是对一个普通的set指令进行压测,QPS大约为 145985.41/s。

root@f5cd3ecb4cd8:/data# redis-benchmark -t set -q

SET: 145985.41 requests per second, p50=0.167 msec

下面加入-P参数,表示单个管道内并行的请求数量,可以看到下面的结果,数量每加1个,QPS会多出十万个左右,从第14个往后,QPS无法提升,甚至开始下降,这是因为CPU的消耗已经达到100%的极限,无法继续提升了。

root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 2 -q

SET: 273224.03 requests per second, p50=0.175 msec                    

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 3 -q

SET: 378795.47 requests per second, p50=0.183 msec                    

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 4 -q

SET: 483091.78 requests per second, p50=0.183 msec      

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 5 -q

SET: 549450.56 requests per second, p50=0.191 msec      

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 6 -q

SET: 653607.88 requests per second, p50=0.199 msec      

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 7 -q

SET: 724652.19 requests per second, p50=0.191 msec      

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 8 -q

SET: 806451.62 requests per second, p50=0.215 msec      

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 9 -q

SET: 877263.19 requests per second, p50=0.255 msec      

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 10 -q

SET: 1408450.62 requests per second, p50=0.255 msec     

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 11 -q

SET: 917440.38 requests per second, p50=0.375 msec      

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 11 -q

SET: 952390.50 requests per second, p50=0.375 msec      

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 12 -q

SET: 1020489.81 requests per second, p50=0.399 msec     

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 13 -q

SET: 1333453.25 requests per second, p50=0.367 msec     

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 14 -q

SET: 1075290.25 requests per second, p50=0.455 msec     

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 15 -q

SET: 1020459.19 requests per second, p50=0.479 msec     

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 16 -q

SET: 1000000.00 requests per second, p50=0.519 msec     

\


root@f5cd3ecb4cd8:/data# redis-benchmark -t set -P 17 -q

SET: 1020520.44 requests per second, p50=0.551 msec
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
缓存 NoSQL 网络协议
Redis之管道解读
Redis之管道解读
|
11月前
|
NoSQL 网络协议 Redis
Redis管道
Redis管道
60 0
|
11月前
|
存储 消息中间件 缓存
Redis 7 事务、管道、发布订阅、主从、哨兵、集群
Redis 7 事务、管道、发布订阅、主从、哨兵、集群
|
NoSQL 网络协议 测试技术
Redis管道技术的使用
Redis管道技术的使用
121 0
Redis管道技术的使用
|
NoSQL Redis
redis管道
pipeline
101 0
|
存储 NoSQL 网络协议
|
NoSQL 网络协议 测试技术
Redis管道Pipelining原理详解
Redis管道Pipelining原理详解
278 0
Redis管道Pipelining原理详解
|
NoSQL 测试技术 调度
Redis进阶实践之十八 使用管道模式提高Redis查询的速度
原文:Redis进阶实践之十八 使用管道模式提高Redis查询的速度 一、引言             学习redis 也有一段时间了,该接触的也差不多了。后来有一天,以为同事问我,如何向redis中批量的增加数据,肯定是大批量的,为了这主题,我从新找起了解决方案。
1325 0
|
消息中间件 NoSQL C#
Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间
原文:Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间 Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间 简介   《Redis 小白指南(一)- 简介、安装、GUI 和 C# 驱动介绍》 讲的是 Redis 的介绍,以及如何在 Windows 上安装并使用,一些 GUI 工具和自己简单封装的 RedisHelper。
1570 0

热门文章

最新文章