简介
Redis 管道 (Pipeline) 本身并不是 Redis 服务器直接提供的技术,这个技术本质上是由客户端提供的,跟服务器没有什么直接的关系。
管道本质:客户端通过对管道中的指令列表改变读写顺序就可以大幅节省 IO 时间
如上图,把两个连续的写操作和两个连续的读操作总共只会花费一次网络来回,就好比连续的 write 操作合并了,连续的 read 操作也合并了一样。
管道压力测试
Redis 自带了一个压力测试工具redis-benchmark,使用这个工具就可以进行管道测试。
首先对一个 set 指令进行压测,QPS 大约为 13w/s。
>redis-benchmark -t set -q
SET: 134589.50 requests per second
我们加入管道选项-P参数,它表示单个管道内并行的请求数量,看下面 P=2,QPS 达到了 27w/s。
>redis-benchmark -t set -P 2 -q
SET: 275482.09 requests per second
开始 随着P值设置的增大,QPS也升高,但如果 CPU 处理能力已经达到了瓶颈,Redis 的单线程 CPU 已经飙到了 100%,就无法再继续提升了。
管道本质
如上图,步骤大概如下:
- 客户端进程调用
write将消息写到操作系统内核为套接字分配的发送缓冲区send buffer中。 - 客户端操作系统内核将
send buffer的内容发送到网卡 - 网卡硬件通过
网际路由发送到服务器网卡 - 服务器操作系统将网卡的数据放入到内核为套接字分配的接受缓冲区
recv buffer中 - 服务器进程调用
read从recv buffer中取出消息进行处理 - 服务器进程调用
write将相应的消息写到内核为套接字分配的发送缓冲区end buffer中 - 接受同上原理
所以,write 操作,并不是等对方收到消息才会返回,实际上 write 只负责将数据写到本地发送缓冲区中就返回了,后续的事情是操作系统内核异步将数据送到目标机器,几乎没有耗时。一旦发送缓冲区满了,那么就需要等待缓冲区空间空闲出来,这就是写操作的IO耗时。
而 read 操作,就比较耗时,他要等待消息经过网络路由到目标机器处理后的相应消息,回送到当前的内核读缓冲区才可以返回,网络来回的开销。
对于管道,连续的 write 操作没有耗时,之后第一个 read 操作会等待一个网络的来回开销。然后所有的响应消息都已经送回内核读缓冲了,后续的read操作直接就可以从缓存中拿到结果瞬间就返回了。