深入理解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 12 Redis
浅谈redis缓存在项目中的使用
May 20 Redis
redis实现共同好友的思路详解
May 26 Redis
Redis可视化客户端小结
Jun 10 Redis
详解Redis在SpringBoot工程中的综合应用
Oct 16 Redis
聊聊redis-dump工具安装问题
Jan 18 Redis
浅谈Redis跟MySQL的双写问题解决方案
Feb 24 Redis
高并发下Redis如何保持数据一致性(避免读后写)
Mar 18 Redis
一文搞懂Redis中String数据类型
Apr 03 Redis
Redis基本数据类型哈希Hash常用操作命令
Jun 01 Redis
使用Redis实现分布式锁的方法
Jun 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个人网站架设连环讲(三)
2006/10/09 PHP
PHP中的正规表达式(一)
2006/10/09 PHP
php中判断数组相等的方法以及数组运算符介绍
2015/03/30 PHP
PHP中模糊查询并关联三个select框
2017/06/19 PHP
PHP时间处理类操作示例
2018/09/05 PHP
js分页工具实例
2015/01/28 Javascript
JS+CSS实现另类带提示效果的竖向导航菜单
2015/10/15 Javascript
AngularJS中比较两个数组是否相同
2016/08/24 Javascript
JavaScript 总结几个提高性能知识点(推荐)
2017/02/20 Javascript
详解webpack+vue-cli项目打包技巧
2017/06/17 Javascript
对于js垃圾回收机制的理解
2017/09/14 Javascript
微信小程序中进行地图导航功能的实现方法
2018/06/29 Javascript
JS使用tween.js动画库实现轮播图并且有切换功能
2018/07/17 Javascript
vue-test-utils初使用详解
2019/05/23 Javascript
Nautil 中使用双向数据绑定的实现
2019/10/02 Javascript
简介Django框架中可使用的各类缓存
2015/07/23 Python
Python Paramiko模块的安装与使用详解
2016/11/18 Python
Python中staticmethod和classmethod的作用与区别
2018/10/11 Python
python如何实现数据的线性拟合
2019/07/19 Python
详解Python 重学requests发起请求的基本方式
2020/02/07 Python
Python多重继承之菱形继承的实例详解
2020/02/12 Python
python中random模块详解
2021/03/01 Python
台湾最大银发乐活百货:乐龄网
2018/05/21 全球购物
俄罗斯第一家多品牌在线奢侈品精品店:Aizel.ru
2020/09/06 全球购物
开办加工厂创业计划书
2014/01/03 职场文书
婚礼新郎父母答谢词
2014/01/16 职场文书
学年末自我鉴定
2014/01/21 职场文书
精彩的广告词
2014/03/19 职场文书
2014年惩防体系建设工作总结
2014/12/01 职场文书
监理中标通知书
2015/04/16 职场文书
2019已经过半,你知道年中工作总结该怎么写吗?
2019/07/03 职场文书
pytest进阶教程之fixture函数详解
2021/03/29 Python
解决Mysql的left join无效及使用的注意事项说明
2021/07/01 MySQL
各种货币符号快捷输入
2022/02/17 杂记
动画「半妖的夜叉姬」新BD特典图公开
2022/03/22 日漫
nginx配置指令之server_name的具体使用
2022/08/14 Servers