Redis 高级特性 Pipeline (管道) 使用和基本测试

 

都说 Pipeline 有很大好处,但是能量是守恒的,好坏也是相对的。 所以我们主要来测试看看 Pipeline 的利弊。 带着几个问题我们来进行基本的测试。 1. Pipeline 对命令数量是否有限制? 2. Pipeline 打包执行多少命令合适? 3. Pipeline 批量执行的时候,是否对Redis进行了锁定,导致其他应用无法再进行读写?

Redis 常规使用方式

我们都知道Redis 是单线程的,那么在常规使用情况下,我们使用 Redis ,如下代码执行是什么流程呢?

$key1 = "abc1";
$key2 = "abc2";
$key3 = "abc3";
$redisObj->set($key1, 1);
$redisObj->set($key2, 2);
$redisObj->set($key3, 3);

PHP

Redis 的执行方式是逐条命令: 发送命令->执行->返回执行结果。

如图: 

什么是 pipeline 呢?

知道了常规的使用方式,那么我们再来看看 pipeline 模式,pipeline 模式则是将执行的命令写入到缓冲中,最后由exec命令一次性发送给redis执行返回。

我们以灌一个list来进行测试,以20000条list数据为例,来对比一下常规模式的的写入和 pipeline 模式的写入。

Redis pipeline 的执行方式: 打包开始->缓存->打包结束->发送->执行->返回执行结果。

如图:

逐条写模式(常规模式)

<?php
$redisObj = new \Redis();
$redisObj->connect('127.0.0.1', 6379);

$time_start = microtime(true);
$mcKey      = "lpush:normal";
for ($i = 0; $i < 20000; $i++)
{
    $redisObj->lPush($mcKey, $i);
}

$time_end = microtime(true);
$time     = $time_end - $time_start;
echo "逐条写模式耗时: {$time}\n";

PHP

Pipeline(管道) 模式

<?php
$redisObj = new \Redis();
$redisObj->connect('127.0.0.1', 6379);

$time_start = microtime(true);
$redisObj->multi(Redis::PIPELINE);
unset($time, $time_end, $mcKey);
$mcKey = "lpush:pipeline";
for ($i = 0; $i < 20000; $i++)
{
    $redisObj->lPush($mcKey, $i);
}
$redisObj->exec();

$time_end = microtime(true);
$time     = $time_end - $time_start;
echo "pipeline 模式运行耗时:{$time}\n";

PHP

我们看看,两者的执行结果:

#php t.php
逐条写模式耗时: 1.0443658828735
pipeline 模式运行耗时:0.045078039169312

Bash

根据结果可以看出,pipeline 模式的耗时比 逐条写模式 提升了20倍。

Pipeline(管道) 的优点:

  1. pipeline 通过打包命令,一次性执行,可以节省 连接->发送命令->返回结果 所产生的往返时间,
  2. 减少的I/O的调用次数。

Pipeline(管道) 的缺点:

  1. pipeline 每批打包的命令不能过多,因为 pipeline 方式打包命令再发送,那么 redis 必须在处理完所有命令前先缓存起所有命令的处理结果。这样就有一个内存的消耗。
  2. pipeline 是责任链模式,这个模式的缺点是,每次它对于一个输入都必须从链头开始遍历(参考Http Server处理请求就能明白),这确实存在一定的性能损耗。
  3. pipeline 不保证原子性,如果要求原子性的,不推荐使用 pipeline

问题解答

Q、Pipeline 对命令数量是否有限制?
A、没有限制,但是打包的命令不能过多,对内存的消耗就越大。

Q、Pipeline 打包执行多少命令合适?
A、查询 Redis 官方文档,根据官方的解释,推荐是以 10k 每批 (*注意:这个是一个参考值,请根据自身实际业务情况调整)。

IMPORTANT NOTE: While the client sends commands using pipelining, the server will be forced to queue the replies, using memory. So if you need to send a lot of commands with pipelining, it is better to send them as batches having a reasonable number, for instance 10k commands, read the replies, and then send another 10k commands again, and so forth. The speed will be nearly the same, but the additional memory used will be at max the amount needed to queue the replies for this 10k commands. https://redis.io/topics/pipelining

Q、Pipeline 批量执行的时候,是否对Redis进行了锁定,导致其他应用无法再进行读写?
A、Redis 采用多路I/O复用模型,非阻塞IO,所以Pipeline批量写入的时候,一定范围内不影响其他的读操作。

不过在编码时请注意,pipeline 期间将“独占”链接,此期间将不能进行非“管道”类型的其他操作,直到 pipeline 关闭;如果你的 pipeline 的指令集很庞大,为了不干扰链接中的其他操作,你可以为 pipeline 操作新建 Client 链接,让 pipeline 和其他正常操作分离在2个 client 中

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值