深入理解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 相关文章推荐
详解RedisTemplate下Redis分布式锁引发的系列问题
Apr 27 Redis
redis 限制内存使用大小的实现
May 08 Redis
Redis 配置文件重要属性的具体使用
May 20 Redis
Django使用redis配置缓存的方法
Jun 01 Redis
分布式Redis Cluster集群搭建与Redis基本用法
Feb 24 Redis
redis数据结构之压缩列表
Mar 21 Redis
源码分析Redis中 set 和 sorted set 的使用方法
Mar 22 Redis
Redis实现一个账号只能登录一个设备
Apr 19 Redis
Redis基本数据类型Zset有序集合常用操作
Jun 01 Redis
Redis keys命令的具体使用
Jun 05 Redis
Redis配置外网可访问(redis远程连接不上)的方法
Dec 24 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 visitFile()遍历指定文件夹函数
2010/08/21 PHP
javascript实现动态CSS换肤技术的脚本
2007/06/29 Javascript
Js动态添加复选框Checkbox的实例方法
2013/04/08 Javascript
js onload事件不起作用示例分析
2013/10/09 Javascript
模拟一个类似百度google的模糊搜索下拉列表
2014/04/15 Javascript
JavaScript中跨域调用Flash的方法
2014/08/11 Javascript
javascript实现汉字转拼音代码分享
2015/04/20 Javascript
基于jQuery全屏焦点图左右切换插件responsiveslides
2015/09/07 Javascript
超漂亮的Bootstrap 富文本编辑器summernote
2016/04/05 Javascript
浅谈JavaScript 执行环境、作用域及垃圾回收
2016/05/31 Javascript
jQuery实现鼠标经过像翻页和描点链接效果
2016/08/08 Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
2016/10/11 Javascript
jQuery中用on绑定事件时需注意的事项
2017/03/19 Javascript
Zepto实现密码的隐藏/显示
2017/04/07 Javascript
webpack项目轻松混用css module的方法
2018/06/12 Javascript
axios异步提交表单数据的几种方法
2019/08/11 Javascript
layui的数据表格+springmvc实现搜索功能的例子
2019/09/28 Javascript
vue前端和Django后端如何查询一定时间段内的数据
2021/02/28 Vue.js
[39:46]完美世界DOTA2联赛PWL S2 LBZS vs Rebirth 第二场 11.25
2020/11/25 DOTA
Python实现类继承实例
2014/07/04 Python
使用Python编写一个在Linux下实现截图分享的脚本的教程
2015/04/24 Python
git进行版本控制心得详谈
2017/12/10 Python
Python实现判断字符串中包含某个字符的判断函数示例
2018/01/08 Python
详解pandas的外部数据导入与常用方法
2019/05/01 Python
75条笑死人的知乎神回复,用60行代码就爬完了
2019/05/06 Python
Falsk 与 Django 过滤器的使用与区别详解
2019/06/04 Python
DJANGO-URL反向解析REVERSE实例讲解
2019/10/25 Python
python 一维二维插值实例
2020/04/22 Python
央视元宵晚会主持串词
2014/03/25 职场文书
学习计划书怎么写
2014/09/15 职场文书
2014年最新个人对照检查材料范文
2014/09/25 职场文书
介绍信怎么写
2015/05/05 职场文书
六年级语文教学反思
2016/03/03 职场文书
工作建议书范文
2019/07/08 职场文书
浅谈MySQL函数
2021/10/05 MySQL
一文了解Java动态代理的原理及实现
2022/07/07 Java/Android