深入理解redis中multi与pipeline


Posted in Redis onJune 02, 2021

背景

由于对redis缓存中数据有批量操作,例如预热缓存数据,或者在列表页批量去获取缓存数据,在使用了multi批量提交事务后,发现redis压力高居不下,而使用了pipeline之后压力回落了平常,也因为这个案例,特在此写个分析与笔记。

multi

简介

标记一个事务块的开始。
事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行。

实现原理

我用php扩展调起redis服务,执行,代码如下:

$redis = new redis();
$redis->connect('127.0.0.1',6379);
$handle = $redis->multi();
$handle->incr('a');
$handle->incr('b');
$handle->exec();

为了查看这期间具体的连接过程,用wireshark监听回环地址端口6379,抓包请求如下图所示:

深入理解redis中multi与pipeline

redis客户端与服务端建立连接后,multi标记事务开始,之后每次执行,服务端返回queued队列标志。查看redis源码src/multi.c文件:

void queueMultiCommand(client *c) {
    multiCmd *mc;
    int j;

    c->mstate.commands = zrealloc(c->mstate.commands,
            sizeof(multiCmd)*(c->mstate.count+1));
    mc = c->mstate.commands+c->mstate.count;
    mc->cmd = c->cmd;
    mc->argc = c->argc;
    mc->argv = zmalloc(sizeof(robj*)*c->argc);
    memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc);
    for (j = 0; j < c->argc; j++)
        incrRefCount(mc->argv[j]);
    c->mstate.count++;
}

在上述源码中可以看到redis服务端每次会把事务块中的命令保存到内存中,上述简介已经解释过最后通过exec命令执行,再看下面示例图的返回结果可以了解到redis服务端一次性返回所有命令执行返回结果。

深入理解redis中multi与pipeline

pipeline

简介

客户端将执行的命令写入到缓冲中,最后由exec命令一次性发送给redis执行返回。

实现原理

同样,用相关代码调用redis抓包;

$redis = new redis();
$redis->connect('127.0.0.1',6379);
$handle = $redis->pipeline();
$handle->incr('a');
$handle->incr('b');
$handle->exec();

继续用wireshark抓包,如下图所示

深入理解redis中multi与pipeline

pipeline 客户端请求包示例图

深入理解redis中multi与pipeline

这上面的图片简要分析一下,pipeline管道操作是需要客户端与服务端的支持,客户端将命令写入缓冲,最后再通过exec命令发送给服务端,服务端通过命令拆分,逐个执行返回结果。

两者的区别

由上面的请求也可以看出了两者最明显的区别是客户端发送请求的方式不一样,具体相关区别如下:

  • pipeline选择客户端缓冲,multi选择服务端缓冲;
  • 请求次数的不一致,multi需要每个命令都发送一次给服务端,pipeline最后一次性发送给服务端,请求次数相对于multi减少
  • multi/exec可以保证原子性,而pipeline不保证原子性

到此这篇关于深入理解redis中multi与pipeline 的文章就介绍到这了,更多相关redis multi与pipeline 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
redis实现排行榜功能
May 24 Redis
解析高可用Redis服务架构分析与搭建方案
Jun 20 Redis
Redis集群新增、删除节点以及动态增加内存的方法
Sep 04 Redis
Window server中安装Redis的超详细教程
Nov 17 Redis
Redis 哨兵机制及配置实现
Mar 25 Redis
Redis实战高并发之扣减库存项目
Apr 14 Redis
Grafana可视化监控系统结合SpringBoot使用
Apr 19 Redis
Redis数据同步之redis shake的实现方法
Apr 21 Redis
Redis全局ID生成器的实现
Jun 05 Redis
关于Redis的主从复制及哨兵问题
Jun 16 Redis
Redis sentinel哨兵集群的实现步骤
Jul 15 Redis
SpringBoot 集成Redis 过程
Jun 02 #Redis
详解Redis基本命令与使用场景
Django使用redis配置缓存的方法
Jun 01 #Redis
详解Redis集群搭建的三种方式
May 31 #Redis
浅谈Redis主从复制以及主从复制原理
5分钟教你docker安装启动redis全教程(全新方式)
May 29 #Redis
详解缓存穿透击穿雪崩解决方案
You might like
用Zend Encode编写开发PHP程序
2010/02/21 PHP
跟我学Laravel之路由
2014/10/15 PHP
discuz论坛更换域名,详细文件修改步骤
2020/12/09 PHP
10个实用的脚本代码工具
2010/05/04 Javascript
JS版的date函数(和PHP的date函数一样)
2014/05/12 Javascript
jQuery控制网页打印指定区域的方法
2015/04/07 Javascript
TypeError document.getElementById(...) is null错误原因
2015/05/18 Javascript
JS实现超精简响应鼠标显示二级菜单代码
2015/09/12 Javascript
Node.js实现文件上传
2016/07/05 Javascript
JS调用某段SQL语句的方法
2016/10/20 Javascript
在DWR中实现直接获取一个JAVA类的返回值的两种方法
2016/12/25 Javascript
BootStrap导航栏问题记录
2017/07/31 Javascript
label+input实现按钮开关切换效果的实例
2017/08/16 Javascript
javascript input输入框模糊提示功能的实现
2017/09/25 Javascript
微信小程序图片选择区域裁剪实现方法
2017/12/02 Javascript
微信小程序swiper组件用法实例分析【附源码下载】
2017/12/07 Javascript
使用VUE+iView+.Net Core上传图片的方法示例
2019/01/04 Javascript
你了解vue3.0响应式数据怎么实现吗
2019/06/07 Javascript
用Python编写一个每天都在系统下新建一个文件夹的脚本
2015/05/04 Python
python 默认参数问题的陷阱
2016/02/29 Python
python 微信好友特征数据分析及可视化
2020/01/07 Python
python matplotlib.pyplot.plot()参数用法
2020/04/14 Python
python 中 .py文件 转 .pyd文件的操作
2021/03/04 Python
纯css3无js实现的Android Logo(有简单动画)
2013/01/21 HTML / CSS
加拿大服装和鞋类零售商:Mark’s
2021/01/04 全球购物
大学生专科学习生活的自我评价
2013/12/07 职场文书
银行学习十八大感想
2014/01/11 职场文书
告诉你怎样写创业计划书
2014/01/27 职场文书
创业者是否需要商业计划书?
2014/02/07 职场文书
网络编辑岗位职责范本
2014/02/10 职场文书
租房协议书
2014/09/12 职场文书
镇党委书记群众路线整改措施思想汇报
2014/10/13 职场文书
2015社区爱国卫生工作总结
2015/04/21 职场文书
2016年学校党支部创先争优活动总结
2016/04/05 职场文书
手把手教你用SpringBoot将文件打包成zip存放或导出
2021/06/11 Java/Android
Python实现制作销售数据可视化看板详解
2021/11/27 Python