深入理解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 14 Redis
Redis持久化与主从复制的实践
Apr 27 Redis
Java Socket实现Redis客户端的详细说明
May 26 Redis
详解Redis基本命令与使用场景
Jun 01 Redis
Redis集群的关闭与重启操作
Jul 07 Redis
分布式Redis Cluster集群搭建与Redis基本用法
Feb 24 Redis
Redis 哨兵机制及配置实现
Mar 25 Redis
浅谈Redis的事件驱动模型
May 30 Redis
Redis实现订单过期删除的方法步骤
Jun 05 Redis
使用Redis实现分布式锁的方法
Jun 16 Redis
Redis sentinel哨兵集群的实现步骤
Jul 15 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
关于mysql 字段的那个点为是定界符
2007/01/15 PHP
PHP中的正则表达式函数介绍
2012/02/27 PHP
分享一个PHP数据流应用的简单例子
2012/06/01 PHP
检查用户名是否已在mysql中存在的php写法
2014/01/20 PHP
mysql desc(DESCRIBE)命令实例讲解
2016/09/24 PHP
一些常用的Javascript函数
2006/12/22 Javascript
JS中Iframe之间传值的方法
2013/03/11 Javascript
JavaScript将Table导出到Excel实现思路及代码
2013/03/13 Javascript
js下拉菜单语言选项简单实现
2013/09/23 Javascript
JS实现控制表格只显示行边框或者只显示列边框的方法
2015/03/31 Javascript
基于JavaScript实现Json数据根据某个字段进行排序
2015/11/24 Javascript
基于BootStrap Metronic开发框架经验小结【四】Bootstrap图标的提取和利用
2016/05/12 Javascript
jquery模拟多级复选框效果的简单实例
2016/06/08 Javascript
ReactNative-JS 调用原生方法实例代码
2016/10/08 Javascript
H5基于iScroll实现下拉刷新和上拉加载更多
2017/07/18 Javascript
Bootstrap Table 在指定列中添加下拉框控件并获取所选值
2017/07/31 Javascript
javaScript中&quot;==&quot;和&quot;===&quot;的区别详解
2018/03/16 Javascript
微信小程序实现默认第一个选中变色效果
2018/07/17 Javascript
详解如何运行vue项目
2019/04/15 Javascript
vue+高德地图实现地图搜索及点击定位操作
2020/09/09 Javascript
VUE+Element实现增删改查的示例源码
2020/11/23 Vue.js
python paramiko实现ssh远程访问的方法
2013/12/03 Python
理解Python中的类与实例
2015/04/27 Python
Python利用ansible分发处理任务
2015/08/04 Python
python 3.74 运行import numpy as np 报错lib\site-packages\numpy\__init__.py
2019/10/06 Python
美国南部最大的家族百货公司:Belk
2017/01/30 全球购物
荷兰皇家航空公司官方网站:KLM Royal Dutch Airlines
2017/12/07 全球购物
Scotch Porter官方网站:男士美容产品
2020/08/31 全球购物
实习期自我鉴定
2013/10/11 职场文书
施工安全协议书
2013/12/11 职场文书
应届中专生自荐书范文
2014/02/13 职场文书
节约粮食标语
2014/06/18 职场文书
党员学习党的群众路线思想汇报(5篇)
2014/09/10 职场文书
2014年幼儿园小班工作总结
2014/12/04 职场文书
超市主管竞聘书
2015/09/15 职场文书
教师学期述职自我鉴定
2019/08/16 职场文书