前言
众所周知 Redis 是一种基于 C/S 架构的高速缓存服务,基于 TCP 协议进行请求和响应。所以每次客户端发起一个请求,监听 Socket 并等待服务端的响应,服务端处理并响应给客户端。
这个过程中产生的时间称之为 RTT(Round Trip Time - 往返时间),如批量写入数据这种情况,每次进行一次请求响应,那这个时间开销将是灾难性的。
好在 Redis 在很早的版本就支持管道(pipelining)这种技术,在类型批量情况下会有极大的好处。
管道(pipelining)
管道并非 Redis 特有,在 Redis 中运用管道的目的是解决多次请求带来的性能问题(如需要写大量的数据到 Redis 中)。
管道可以实现客户端无需等待服务端的响应继续请求服务端,在最后得到响应。
当使用管道发生命令时候,Redis 服务端会使用一个队列来存储响应。所以为了避免使用过多的内存,可以将命令集切割成多次请求。
性能测试
测试目的:
测试使用管道和不使用管道下,将三百万多条数据写入 Redis 的用时对比。
测试对象:
- 文件存储了 3592666 条数据,文件大小大约为 164M 。内容基本类似:
set rta_00000000000000000860173040670378 30
- 使用管道需要将文件内容转化为 Redis 报文格式(RESP), 关于 RESP 可查阅博文《Redis - 通信协议RESP(附自写 redis 客户端)》。如下所示:
*3
$3
SET
$7
library
$7
library
测试环境:
电脑:Mac mini 16G
Redis 版本:3.2.9
RDB:开启
save 900 1
save 300 10
save 60 10000
AOF:未开启
测试结果:
keys.log 文件中每行如: set rta_00000000000000000860173040670378 30
resp.log 文件中为 resp 报文格式
是否使用管道 | 测试用例 | 备注 | 用时 |
---|---|---|---|
是 | cat keys.log | redis-cli | 直接将 set 命令写入redis | 2m30s |
否 | cat resp.log | redis-cli --pipe | 使用 --pipe 参数代表使用通道 | 8.3s |
总结和注意
- 相较于普通模式,使用通道实现多命令请求的效率是很高的。
- 当单次写入的命令过多,尽管使用通道也要进行拆分多次。避免响应队列过长占用过多的内存。