深入理解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
Redis IP地址的绑定的实现
May 08 Redis
Redis Cluster 字段模糊匹配及删除
May 27 Redis
压缩Redis里的字符串大对象操作
Jun 23 Redis
浅谈Redis位图(Bitmap)及Redis二进制中的问题
Jul 15 Redis
Window server中安装Redis的超详细教程
Nov 17 Redis
SpringBoot整合Redis入门之缓存数据的方法
Nov 17 Redis
Spring Boot实战解决高并发数据入库之 Redis 缓存+MySQL 批量入库问题
Feb 12 Redis
Redis调用Lua脚本及使用场景快速掌握
Mar 16 Redis
浅谈Redis 中的过期删除策略和内存淘汰机制
Apr 03 Redis
Redis数据同步之redis shake的实现方法
Apr 21 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 上传文件大小限制
2009/07/05 PHP
PHP 冒泡排序算法的实现代码
2010/08/08 PHP
PHP列出MySQL中所有数据库的方法
2015/03/12 PHP
Laravel4中的Validator验证扩展用法详解
2016/07/26 PHP
不要在cookie中使用特殊字符的原因分析
2010/07/13 Javascript
js取滚动条的尺寸的函数代码
2011/11/30 Javascript
javascript同页面多次调用弹出层具体实例代码
2013/08/16 Javascript
热点新闻滚动特效的js代码
2013/08/17 Javascript
js获取下拉列表框中的value和text的值示例代码
2014/01/11 Javascript
js全选按钮的实现方法
2015/11/17 Javascript
详解AngularJs中$sce与$sceDelegate上下文转义服务
2016/09/21 Javascript
javascript history对象详解
2017/02/09 Javascript
mui上拉加载功能实例详解
2017/04/13 Javascript
vue elementui form表单验证的实现
2018/11/11 Javascript
Vue唯一可以更改vuex实例中state数据状态的属性对象Mutation的讲解
2019/01/18 Javascript
elementUI select组件默认选中效果实现的方法
2019/03/25 Javascript
JavaScript this指向相关原理及实例解析
2020/07/10 Javascript
[01:03:59]2018DOTA2亚洲邀请赛3月30日 小组赛B组VGJ.T VS Secret
2018/03/31 DOTA
[59:44]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 paiN vs iG
2018/03/31 DOTA
nohup后台启动Python脚本,log不刷新的解决方法
2019/01/14 Python
python按键按住不放持续响应的实例代码
2019/07/17 Python
python tornado修改log输出方式
2019/11/18 Python
python selenium自动化测试框架搭建的方法步骤
2020/06/14 Python
python实现登录与注册系统
2020/11/30 Python
英国著名音像制品和图书游戏购物网站:Zavvi
2016/08/04 全球购物
英国家居用品和床上用品零售商:P&B Home
2020/01/16 全球购物
中间件分为哪几类
2012/03/14 面试题
How to spawning asynchronous work in J2EE
2016/08/29 面试题
汽车机修工岗位职责
2014/03/06 职场文书
授权委托书怎么写
2014/09/25 职场文书
解除租房协议书
2014/12/03 职场文书
企业2014年度工作总结
2014/12/10 职场文书
复兴之路观后感
2015/06/02 职场文书
2015年机关作风和效能建设工作总结
2015/07/23 职场文书
员工工作失职检讨书范文!
2019/07/03 职场文书
Vue 打包后相对路径的引用问题
2022/06/05 Vue.js