深入理解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实现限流的三种方式
Apr 27 Redis
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
May 21 Redis
redis客户端实现高可用读写分离的方式详解
Jul 04 Redis
厉害!这是Redis可视化工具最全的横向评测
Jul 15 Redis
Redis字典实现、Hash键冲突及渐进式rehash详解
Sep 04 Redis
源码分析Redis中 set 和 sorted set 的使用方法
Mar 22 Redis
Redis如何使用乐观锁(CAS)保证数据一致性
Mar 25 Redis
redis 解决库存并发问题实现数量控制
Apr 08 Redis
Redis特殊数据类型HyperLogLog基数统计算法讲解
Jun 01 Redis
浅谈Redis缓冲区机制
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
优化php效率,提高php性能的一些方法
2011/03/24 PHP
PHP过滤★等特殊符号的正则
2014/01/27 PHP
推荐5款跨平台的PHP编辑器
2014/12/25 PHP
Yii2中SqlDataProvider用法示例
2016/09/22 PHP
php封装的mysqli类完整实例
2016/10/18 PHP
解决在laravel中auth建立时候遇到的问题
2019/10/15 PHP
对textarea框的代码调试,而且功能上使用非常方便,酷
2006/06/30 Javascript
javascript操作文本框readOnly
2007/05/15 Javascript
javascript 词法作用域和闭包分析说明
2010/08/12 Javascript
jQuery Deferred和Promise创建响应式应用程序详细介绍
2013/03/05 Javascript
JQuery节点元素属性操作方法
2015/06/11 Javascript
AngularJS入门教程二:在路由中传递参数的方法分析
2017/05/27 Javascript
Node.js实现文件上传的示例
2017/06/28 Javascript
Vue动态组件实例解析
2017/08/20 Javascript
用JavaScript做简易的购物车的代码示例
2017/10/20 Javascript
js最实用string(字符串)类型的使用及截取与拼接详解
2019/04/26 Javascript
js console.log打印对象时属性缺失的解决方法
2019/05/23 Javascript
详解Java中String JSONObject JSONArray List转换
2020/11/13 Javascript
JavaScript canvas实现雨滴特效
2021/01/10 Javascript
举例讲解Python面向对象编程中类的继承
2016/06/17 Python
Python实现购物系统(示例讲解)
2017/09/13 Python
教你用一行Python代码实现并行任务(附代码)
2018/02/02 Python
Python图像处理之识别图像中的文字(实例讲解)
2018/05/10 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
Python将json文件写入ES数据库的方法
2019/04/10 Python
python如何从键盘获取输入实例
2020/06/18 Python
详解CSS3选择器:nth-child和:nth-of-type之间的差异
2017/09/18 HTML / CSS
即时搜索数百万张门票:SeatsForEveryone.com
2018/08/26 全球购物
装修设计师求职信
2014/02/26 职场文书
公司授权委托书
2014/04/04 职场文书
个人综合鉴定材料
2014/05/23 职场文书
体育教师个人工作总结
2015/02/09 职场文书
2015年初中教务处工作总结
2015/07/21 职场文书
PHP 对接美团大众点评团购券(门票)的开发步骤
2021/04/03 PHP
Python类方法总结讲解
2021/07/26 Python
详解apache编译安装httpd-2.4.54及三种风格的init程序特点和区别
2022/07/15 Servers