详解redis 中Pipeline流水线机制

详解redis 中Pipeline流水线机制

大家好,又见面了,我是全栈君。

一、pipeline出现的背景:

redis客户端执行一条命令分4个过程:

发送命令-〉命令排队-〉命令执行-〉返回结果

这个过程称为Round trip time(简称RTT, 往返时间),mget mset有效节约了RTT,但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要消耗N次RTT ,这个时候需要pipeline来解决这个问题。

二、pepeline的性能

1、未使用pipeline执行N条命令

详解redis 中Pipeline流水线机制

2、使用了pipeline执行N条命令

详解redis 中Pipeline流水线机制

3、两者性能对比

详解redis 中Pipeline流水线机制

小结:这是一组统计数据出来的数据,使用Pipeline执行速度比逐条执行要快,特别是客户端与服务端的网络延迟越大,性能体能越明显.

三、原生批命令(mset, mget)与Pipeline对比

1、原生批命令是原子性,pipeline是非原子性

(原子性概念:一个事务是一个不可分割的最小工作单位,要么都成功要么都失败。原子操作是指你的一个业务逻辑必须是不可拆分的. 处理一件事情要么都成功,要么都失败,原子不可拆分)

2、原生批命令一命令多个key, 但pipeline支持多命令(存在事务),非原子性

3、原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成

四、Pipeline正确使用方式

在下面代码里,我用了一个用户名数组,数组元素的key值是用户对应的id,一旦用户修改了其用户名,我将修改两个redis值:

  • 当前用户其用户名修改次数需要+1

  • 更新当前用户对应的用户名数据

$redis = new Redis();

//开启管道模式,代表将操作命令暂时放在管道里
$pipe = $redis->multi(Redis::PIPELINE);

//循环遍历数据,执行操作
foreach ($users as $user_id => $username)
{
    //用户名修改次数+1
    $pipe->incr('changes:' . $user_id);

    // 更新用户名
    $pipe->set('user:' . $user_id . ':username', $username);
}

//开始执行管道里所有命令
$pipe->exec();

管道里放什么操作,并没有什么限制,即使你放获取数据的操作也是ok的。
现在就假设我们要给某个redis key值+1,但是获取另一个redis key值的value数据。
如下代码就是一个操作是更新某个用户被访问的次数,另一个操作则是获取用户信息数据。

$redis = new Redis();

//开启管道模式
$pipe = $redis->multi(Redis::PIPELINE);

//循环遍历数据,执行操作
foreach ($users as $user_id => $username)
{
    // 用户被访问的次数+1
    $pipe->incr('accessed:' . $user_id);

    // 获取用户数据记录
    $pipe->get('user:' . $user_id);
}
// 开始执行管道里所有命令
$users = $pipe->exec();

// 打印数据
print_r($users);

注意,由于管道里每一条命令都会返回数据,所以最终打印的数组,会含有incr操作带来的记录,还有从获取用户操作那里拉下来的redis key值作为了打印数组的索引值。

不过有个好处,管道里每个操作命令返回的数据是按照管道里顺序存储的,key值是0,1,2这种。我们想要啥数据,自己稍微处理一下就好啦。

如果我们像取消管道操作,用下面代码即可:

$pipe->discard();

总结:pipeline 虽然好用,但是每次pipeline 每次组装的命令个数不能没有节制,否则一次组装pipeline数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的pipeline拆分成多次较小的pipeline来完成。

详解redis 中Pipeline流水线机制

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111449.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 怎么设置超链接网址css,css应该怎么设置超链接样式「建议收藏」

    怎么设置超链接网址css,css应该怎么设置超链接样式「建议收藏」css设置超链接样式的方法是,给超链接添加伪类,例如【a:visited{color:#00FF00;}】。【a:visited】表示用户已经访问过的链接。本文操作环境:windows10系统、css3、thinkpadt480电脑。如果我们要设置超链接的样式,其实是可以使用任何一个css属性的,比如颜色、字体、背景等等。但是如果你想设置特别的样式,就需要使用到伪类。下面我们一起来看下伪类。…

    2022年7月19日
    22
  • [bzoj4195][Noi2015]程序自动分析

    [bzoj4195][Noi2015]程序自动分析

    2021年6月29日
    76
  • string s=new string(“hello”)_result of string concatenation

    string s=new string(“hello”)_result of string concatenation—問題———我的页面上分别有两个按钮Button1,Button2,和两个编辑框TextBox1,TextBox2,我在PAGE_LOAD里加上下面这行代码后,     TextBox1.Attributes.Add(“onkeydown”,”if(event.keyCode==13){document.all.Button1.click();}”);     实现了对Te

    2022年9月26日
    5
  • 变长数组VLA_数组的大小长度可以改变吗

    变长数组VLA_数组的大小长度可以改变吗C99标准中,支持变长数组,即方括号[]中可以用为一个变量,但是很多编译器并不能很好地支持。c++11标准中,不支持变长数组,即方括号[]中必须为常量表达式。c++标准支不支持变长数组,并不重要,因为完全可以自己实现。变长数组(VLA):即在运行时候确定数组的长度静态数组:编译时数组长度就定死了,不能对数组进行增、删、改动态数组:运行时才确定数组的长度,可以对数组进行增、删、改…

    2025年7月27日
    4
  • mysql报错1396_mysql连接不上数据库

    mysql报错1396_mysql连接不上数据库我似乎无法重新创建一个已删除的简单用户,即使以root用户身份在MySQL中也是如此。我的情况是:用户’jack’曾经存在,但是我从mysql.user中删除了它以重新创建它。我在那张桌子上看不到任何痕迹。如果我对其他随机用户名(例如“jimmy”)执行此命令,则该命令会正常工作(就像最初对“jack”所做的一样)。我已经做了些什么来破坏用户“jack”,以及如何撤销该破坏,以便重新创建“…

    2022年8月12日
    6
  • 数据库学习笔记【自学教程】—— 如何建立数据库

    数据库学习笔记【自学教程】—— 如何建立数据库PS:本项目将在D盘下创建名为Test的文件夹(D:/Test)。如若想修改文件位置,需在后续代码中一并修改。点击工具栏“新建查询”或者使用快捷键Ctrl+N==>打开查询分析器SQLServer中,一个数据库至少包括两个文件。一个是主数据文件,一个是日志文件。一、建立数据库1)通过语句建立数据库新建一个名为“教师授课管理数据库”的数据库,代码如下:CREATEDATABASE教师授课管理数据库ON(NAME=T…

    2025年11月26日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号