服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Redis - 深入理解redis中multi与pipeline

深入理解redis中multi与pipeline

2021-08-09 17:41Walker5883 Redis

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

背景

由于对redis缓存中数据有批量操作,例如预热缓存数据,或者在列表页批量去获取缓存数据,在使用了multi批量提交事务后,发现redis压力高居不下,而使用了pipeline之后压力回落了平常,也因为这个案例,特在此写个分析与笔记。

multi

简介

标记一个事务块的开始。
事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 exec 命令原子性(atomic)地执行。

实现原理

我用php扩展调起redis服务,执行,代码如下:

?
1
2
3
4
5
6
$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文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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抓包;

?
1
2
3
4
5
6
$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 内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/6844903635252412430

延伸 · 阅读

精彩推荐
  • RedisRedis如何实现分布式锁

    Redis如何实现分布式锁

    相信大家对锁已经不陌生了,本文主要介绍了Redis如何实现分布式锁,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    公众号程序员学长11082021-09-17
  • RedisRedis挂了,流量把数据库也打挂了,怎么办?

    Redis挂了,流量把数据库也打挂了,怎么办?

    Redis 挂了,不就是缓存都没了吗?缓存都没了,不就是缓存雪崩了吗?缓存雪崩了,不就导致数据库挂了吗?一提到“缓存雪崩”这四个字,缓存穿透、缓存击...

    why技术8672021-08-11
  • Redis浅谈Redis中的内存淘汰策略和过期键删除策略

    浅谈Redis中的内存淘汰策略和过期键删除策略

    本文主要介绍了浅谈Redis中的内存淘汰策略和过期键删除策略,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    纪先生9002021-11-14
  • RedisRedis面试题常见问答

    Redis面试题常见问答

    通常,我们会使用缓存用于缓冲对 DB 的冲击,如果缓存宕机,所有请求将直接打在 DB,造成 DB 宕机——从而导致整个系统宕机。...

    民工哥技术之路3082020-07-18
  • RedisWindows下Redis的安装使用教程

    Windows下Redis的安装使用教程

    这篇文章主要以图文结合的方式为大家详细介绍了Windows下Redis的安装使用,Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对...

    CSDN3952019-10-29
  • Redis简单实用!利用Redis轻松实现高并发全局ID生成器

    简单实用!利用Redis轻松实现高并发全局ID生成器

    Redis作为高性能的KV数据库,并且操作还是原子性的,所以用来做支持高并发的发号器十分合适。 本文给大家介绍3种常见的全局ID生成方式。 1、全局递增...

    未知802023-05-07
  • Redis一次关于Redis内存诡异增长的排查过程实战记录

    一次关于Redis内存诡异增长的排查过程实战记录

    这篇文章主要给大家分享了一次关于Redis内存诡异增长的排查过程实战记录,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis具有一定的参考学...

    付磊2962019-11-15
  • Redis使用Redis实现用户积分排行榜的教程

    使用Redis实现用户积分排行榜的教程

    这篇文章主要介绍了使用Redis实现用户积分排行榜的教程,包括一个用PHP脚本进行操作的例子,需要的朋友可以参考下 ...

    Redis教程网4572019-10-23