深入理解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 24 Redis
redis内存空间效率问题的深入探究
May 17 Redis
详解redis分布式锁的这些坑
May 19 Redis
详解Redis主从复制实践
May 19 Redis
浅谈redis整数集为什么不能降级
Jul 25 Redis
使用RedisTemplat实现简单的分布式锁
Nov 20 Redis
关于使用Redisson订阅数问题
Jan 18 Redis
基于Redis zSet实现滑动窗口对短信进行防刷限流的问题
Feb 12 Redis
在Centos 8.0中安装Redis服务器的教程详解
Mar 21 Redis
Redis分布式锁的7种实现
Apr 01 Redis
Redis keys命令的具体使用
Jun 05 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
基于empty函数的输出详解
2013/06/17 PHP
php实现webservice实例
2014/11/06 PHP
php实现读取和写入tab分割的文件
2015/06/01 PHP
php递归函数三种实现方法及如何实现数字累加
2015/08/07 PHP
PHP第三方登录―QQ登录实现方法
2017/02/06 PHP
浅谈php://filter的妙用
2019/03/05 PHP
PJ Blog修改-禁止复制的代码和方法
2006/10/25 Javascript
jquery 图片截取工具jquery.imagecropper.js
2010/04/09 Javascript
jquery.boxy插件的iframe扩展代码
2010/07/02 Javascript
线路分流自动智能跳转代码,自动选择最快镜像网站(js)
2011/10/31 Javascript
JavaScript也谈内存优化
2014/06/06 Javascript
轻松创建nodejs服务器(1):一个简单nodejs服务器例子
2014/12/18 NodeJs
JS如何实现文本框随文本的长度而增长
2015/07/30 Javascript
JS获取checkbox的个数简单实例
2016/08/19 Javascript
Vue.js开发环境搭建
2016/11/10 Javascript
基于JavaScript实现右键菜单和拖拽功能
2016/11/28 Javascript
js输入框使用正则表达式校验输入内容的实例
2017/02/12 Javascript
解决elementUI 切换tab后 el_table 固定列下方多了一条线问题
2020/07/19 Javascript
动态实现element ui的el-table某列数据不同样式的示例
2021/01/22 Javascript
pycharm 使用心得(一)安装和首次使用
2014/06/05 Python
Python实现在tkinter中使用matplotlib绘制图形的方法示例
2018/01/18 Python
win7下python3.6安装配置方法图文教程
2018/07/31 Python
python K近邻算法的kd树实现
2018/09/06 Python
python-tkinter之按钮的使用,开关方法
2019/06/11 Python
Python(PyS60)实现简单语音整点报时
2019/11/18 Python
Python利用Scrapy框架爬取豆瓣电影示例
2020/01/17 Python
Python就将所有的英文单词首字母变成大写
2021/02/12 Python
HTML 5 input placeholder 属性如何完美兼任ie
2014/05/12 HTML / CSS
Avène雅漾美国官方网站:敏感肌肤护理专家
2016/10/24 全球购物
英国工艺品购物网站:Minerva Crafts
2018/01/29 全球购物
《社戏》教学反思
2014/04/15 职场文书
律师授权委托书范本
2014/10/07 职场文书
Redis数据结构之链表与字典的使用
2021/05/11 Redis
浅析CSS在DevTools 中架构演变
2021/10/05 HTML / CSS
Python Matplotlib绘制动画的代码详解
2022/05/30 Python
Nginx配置使用详解
2022/07/07 Servers