深入理解redis中multi与pipeline

 更新时间:2021年06月02日 11:38:00   作者:Walker5883  
pipeline 只是把多个redis指令一起发出去,redis并没有保证这些指定的执行是原子的;multi相当于一个redis的transaction的,保证整个操作的原子性,避免由于中途出错而导致最后产生的数据不一致。本文详细的介绍,感兴趣的可以了解一下

背景

由于对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标记事务开始,之后每次执行,服务端返回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服务端一次性返回所有命令执行返回结果。

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抓包,如下图所示

pipeline 客户端请求包示例图

这上面的图片简要分析一下,pipeline管道操作是需要客户端与服务端的支持,客户端将命令写入缓冲,最后再通过exec命令发送给服务端,服务端通过命令拆分,逐个执行返回结果。

两者的区别

由上面的请求也可以看出了两者最明显的区别是客户端发送请求的方式不一样,具体相关区别如下:

  • pipeline选择客户端缓冲,multi选择服务端缓冲;
  • 请求次数的不一致,multi需要每个命令都发送一次给服务端,pipeline最后一次性发送给服务端,请求次数相对于multi减少
  • multi/exec可以保证原子性,而pipeline不保证原子性

到此这篇关于深入理解redis中multi与pipeline 的文章就介绍到这了,更多相关redis multi与pipeline 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Redis缓存时高效的批量删除的几种方案

    使用Redis缓存时高效的批量删除的几种方案

    这篇文章主要介绍了使用Redis缓存时高效的批量删除的几种方案的相关资料,需要的朋友可以参考下
    2023-01-01
  • redis启动失败问题之完美解决方案

    redis启动失败问题之完美解决方案

    这篇文章主要介绍了redis启动失败问题之完美解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Redis服务器的启动过程分析

    Redis服务器的启动过程分析

    这篇文章主要介绍了Redis服务器的启动过程分析,本文讲解了初始化Redis服务器全局配置、加载配置文件、初始化服务器、加载数据、开始网络监听等内容,需要的朋友可以参考下
    2015-04-04
  • redis实现延时队列的两种方式(小结)

    redis实现延时队列的两种方式(小结)

    这篇文章主要介绍了redis实现延时队列的两种方式(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Redis主从复制详解

    Redis主从复制详解

    今天小编就为大家分享一篇关于Redis主从复制详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • CentOS6.4 安装Redis 教程详解

    CentOS6.4 安装Redis 教程详解

    这篇文章主要介绍了CentOS6.4 安装Redis 教程详解,需要的朋友可以参考下
    2017-05-05
  • Redis定期删除过期数据的操作流程

    Redis定期删除过期数据的操作流程

    Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态,本文给大家介绍了Redis定期删除过期数据的操作流程,文中通过代码示例介绍的讲解的非常详细,需要的朋友可以参考下
    2024-05-05
  • Redis实战之百度首页新闻热榜的实现代码

    Redis实战之百度首页新闻热榜的实现代码

    这篇文章主要介绍了Redis实战之百度首页新闻热榜的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • Redis协议具体用法详解

    Redis协议具体用法详解

    在本篇文章中小编给大家整理了关于Redis协议具体用法以及相关内容知识点,需要的朋友们学习下。
    2019-06-06
  • Redis节省内存的十个技巧分享

    Redis节省内存的十个技巧分享

    你是否在工作中遇到过Redis的bigkey导致的内存占用严重、查询耗时大大增加?同时bigKey还可能导致Redis实例的崩溃,因为内存不够用了,所以本文给大家介绍了Redis极大节省内存的10个技巧,需要的朋友可以参考下
    2024-04-04

最新评论