深入理解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 13 Redis
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
May 21 Redis
浅谈Redis主从复制以及主从复制原理
May 29 Redis
redis使用不当导致应用卡死bug的过程解析
Jul 01 Redis
redis客户端实现高可用读写分离的方式详解
Jul 04 Redis
解析redis hash应用场景和常用命令
Aug 04 Redis
Redis分布式锁Redlock的实现
Aug 07 Redis
Redis入门教程详解
Aug 30 Redis
在项目中使用redis做缓存的一些思路
Sep 14 Redis
Redis超详细讲解高可用主从复制基础与哨兵模式方案
Apr 07 Redis
Redis如何实现验证码发送 以及限制每日发送次数
Apr 18 Redis
Redis唯一ID生成器的实现
Jul 07 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 $_ENV为空的原因分析
2009/06/01 PHP
PHP 压缩文件夹的类代码
2009/11/05 PHP
php获取mysql数据库中的所有表名的代码
2011/04/23 PHP
php 无法加载mcrypt.dll的解决办法
2013/04/03 PHP
探讨php define()函数及defined()函数使用详解
2013/06/09 PHP
php 三大特点:封装,继承,多态
2017/02/19 PHP
tp5框架无刷新分页实现方法分析
2019/09/26 PHP
JavaScript中出现乱码的处理心得
2009/12/24 Javascript
jquery中对表单的基本操作代码
2010/07/29 Javascript
一个简单的JavaScript数据缓存系统实现代码
2010/10/24 Javascript
基于jquery实现的鼠标拖拽元素复制并写入效果
2011/08/23 Javascript
javascript学习笔记(九) js对象 设计模式
2012/06/19 Javascript
js从10种颜色中随机取色实现每次取出不同的颜色
2013/10/23 Javascript
详谈LABJS按需动态加载js文件
2015/05/07 Javascript
深入理解Java线程编程中的阻塞队列容器
2015/12/07 Javascript
基于jQuery和CSS3制作响应式水平时间轴附源码下载
2015/12/20 Javascript
Hammer.js+轮播原理实现简洁的滑屏功能
2016/02/02 Javascript
js select下拉联动 更具级联性!
2020/04/17 Javascript
javascript 使用正则test( )第一次是 true,第二次是false
2017/02/22 Javascript
实例详解vue.js浅度监听和深度监听及watch用法
2018/08/16 Javascript
详解Vue 动态组件与全局事件绑定总结
2018/11/11 Javascript
vue刷新页面时去闪烁提升用户体验效果的实现方法
2018/12/10 Javascript
javascript json字符串到json对象转义问题
2019/01/22 Javascript
Vue实现简单计算器案例
2020/02/25 Javascript
解决vue单页面应用打包后相对路径、绝对路径相关问题
2020/08/14 Javascript
python 阶乘累加和的实例
2019/02/01 Python
python字典嵌套字典的情况下找到某个key的value详解
2019/07/10 Python
Python定时从Mysql提取数据存入Redis的实现
2020/05/03 Python
用python给csv里的数据排序的具体代码
2020/07/17 Python
python 批量下载bilibili视频的gui程序
2020/11/20 Python
如何使用html5与css3完成google涂鸦动画
2012/12/16 HTML / CSS
厨师长岗位职责
2014/03/02 职场文书
四风问题班子对照检查材料
2014/09/27 职场文书
2019年七夕情人节浪漫祝福语大全!
2019/08/08 职场文书
Python初学者必备的文件读写指南
2021/06/23 Python
使用 Koa + TS + ESLlint 搭建node服务器的过程详解
2022/05/30 NodeJs