深入理解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持久化与主从复制的实践
Apr 27 Redis
SpringBoot 集成Redis 过程
Jun 02 Redis
Windows下redis下载、redis安装及使用教程
Jun 02 Redis
缓存替换策略及应用(以Redis、InnoDB为例)
Jul 25 Redis
Redis集群新增、删除节点以及动态增加内存的方法
Sep 04 Redis
使用redis实现延迟通知功能(Redis过期键通知)
Sep 04 Redis
基于Redis结合SpringBoot的秒杀案例详解
Oct 05 Redis
CentOS8.4安装Redis6.2.6的详细过程
Nov 20 Redis
redis的list数据类型相关命令介绍及使用
Jan 18 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
Redis 的查询很快的原因解析及Redis 如何保证查询的高效
Mar 16 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
PHP对文件夹递归执行chmod命令的方法
2015/06/19 PHP
如何使用GDB调试PHP程序
2015/12/08 PHP
ECMAScript 基础知识
2007/06/29 Javascript
JS 学习笔记 防止发生命名冲突
2009/07/30 Javascript
基于Jquery的仿Windows Aero弹出窗(漂亮的关闭按钮)
2010/09/28 Javascript
浏览器解析js生成的html出现样式问题的解决方法
2012/04/16 Javascript
node.js中的path.normalize方法使用说明
2014/12/08 Javascript
javascript实现列表滚动的方法
2015/07/30 Javascript
JS创建对象几种不同方法详解
2016/03/01 Javascript
JS验证逗号隔开可以是中文字母数字
2016/04/22 Javascript
温习Javascript基础语法之词法结构
2016/05/31 Javascript
AngularJs 国际化(I18n/L10n)详解
2016/09/01 Javascript
JavaScript基于DOM操作实现简单的数学运算功能示例
2017/01/16 Javascript
微信小程序通过api接口将json数据展现到小程序示例
2017/01/20 Javascript
Vue2.0用 watch 观察 prop 变化(不触发)
2017/09/08 Javascript
用最少的JS代码写出贪吃蛇游戏
2018/01/12 Javascript
ExtJs使用自定义插件动态保存表头配置(隐藏或显示)
2018/09/25 Javascript
JS获取月的第几周和年的第几周实例代码
2018/12/05 Javascript
使用koa2创建web项目的方法步骤
2019/03/12 Javascript
非常漂亮的js烟花效果
2020/03/10 Javascript
详解JavaScript执行模型
2020/11/16 Javascript
python实现人人网登录示例分享
2014/01/19 Python
python插入排序算法实例分析
2015/07/03 Python
TF-IDF与余弦相似性的应用(二) 找出相似文章
2017/12/21 Python
pandas.DataFrame 根据条件新建列并赋值的方法
2018/04/08 Python
python使用插值法画出平滑曲线
2018/12/15 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
python爬虫 爬取超清壁纸代码实例
2019/08/16 Python
python3+opencv生成不规则黑白mask实例
2020/02/19 Python
Python基础教程(一)——Windows搭建开发Python开发环境
2020/07/20 Python
基于logstash实现日志文件同步elasticsearch
2020/08/06 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
2020/11/05 Python
《池塘边的叫声》教学反思
2014/04/12 职场文书
离婚案件答辩状
2015/05/22 职场文书
三八红旗手主要事迹材料
2015/11/04 职场文书
javascript中Set、Map、WeakSet、WeakMap区别
2022/12/24 Javascript