Redis系列(九):Redis的事务机制

Redis系列(九):Redis的事务机制Redis的事务机制。

Redis系列(九):Redis的事务机制

提到事务,相信大家都不陌生,事务的ACID四大特性,也是面试时经常问的,不过一般情况下,我们可能想到的是传统关系型数据库的事务,其实,Redis也是提供了事务机制的,本篇博客就来讲解下Redis的事务机制。

1. 事务演示

Redis的事务提供了一种将多个命令请求打包,然后一次性、按顺序性地执行多个命令的机制。

在事务执行期间,服务器不会中断事务而去执行其它客户端的命令请求,它会将事务中的所有命令执行完毕,然后才去处理其它客户端的命令请求。

下图展示了一个Redis事务的执行过程:

Redis系列(九):Redis的事务机制

可以看出,事务以MULTI命令开始,然后将多个命令放到事务当中,最后由EXEC命令将这个事务提交给服务器执行。

2. 事务实现原理

一个事务从开始到结束会经历以下3个阶段:

  1. 事务开始
  2. 命令入队
  3. 事务执行

2.1 事务开始

MULTI命令的执行标志着事务的开始。

Redis系列(九):Redis的事务机制

执行完该命令后,客户端状态的flags属性会打开REDIS_MULTI标识,表示该客户端从非事务状态切换至事务状态。

2.2 命令入队

当一个客户端处于非事务状态时,这个客户端发送的命令会立即被服务器执行:

Redis系列(九):Redis的事务机制

当一个客户端处于事务状态时,这个客户端发送的命令,服务器是否会立即执行,分为以下2种情况:

  1. 如果客户端发送的命令为MULTIEXECWATCHDISCARD四个命令中的其中1个,服务器会立即执行这个命令。
  2. 如果客户端发送的命令为以上4个命令外的其它命令,服务器不会立即执行这个命令,而是将其放到事务队列里,然后向客户端返回QUEUED回复。

Redis系列(九):Redis的事务机制

以上流程可以使用以下流程图来表示:

Redis系列(九):Redis的事务机制

这里首先提下DISCARD命令,这个命令用于取消事务,放弃执行事务块内的所有命令,如下所示:

Redis系列(九):Redis的事务机制

然后提下事务队列,每个Redis客户端都有自己的事务状态,事务状态存储在客户端状态的mstates属性里:

Redis系列(九):Redis的事务机制

事务状态包含1个事务队列和1个已入队命令的数量,如下所示:

Redis系列(九):Redis的事务机制

事务队列是一个multiCmd类型的数组,数组中的每个multiCmd结构保存了一个已入队命令的相关信息,比如:

  1. 指向命令实现函数的指针,如GET命令、SET命令
  2. 命令的参数
  3. 参数的数量

事务队列以先进先出(FIFO)的方式保存入队的命令。

2.3 事务执行

当一个处于事务状态的客户端执行EXEC命令时,服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令(按先入先出顺序),然后将执行命令的结果一次性返回给客户端。

Redis系列(九):Redis的事务机制

3. WATCH命令的实现原理

WATCH命令用于监视任意数量的数据库键,并在EXEC命令执行时,检测被监视的键是否被修改,如果被修改了,服务器将拒绝执行事务,并向客户端返回空回复。

为了更好的理解,我们做个演示,首先,我们打开客户端1,执行WATCH命令监视键“name”,然后开启一个事务:

Redis系列(九):Redis的事务机制

此时,先不要执行EXEC命令,打开客户端2,执行以下命令修改“name”键的值:

Redis系列(九):Redis的事务机制

然后,在客户端1执行EXEC命令时,会返回空回复,因为“name”键的值在客户端2已经被修改:

Redis系列(九):Redis的事务机制

那么,WATCH命令的实现原理是什么样的呢?我们从以下3个方面来分析:

  1. 使用WATCH命令监视数据库键
  2. 监视机制的触发
  3. 判断事务是否安全

3.1 使用WATCH命令监视数据库键

每个Redis数据库都保存着1个watched_keys字典,这个字典的键是某个被WATCH命令监视的数据库键,字典的值是一个链表,链表中记录了所有监视相应数据库键的客户端。

Redis系列(九):Redis的事务机制

举个例子,假如客户端1正在监视键“name”,客户端2正在监视键“age”,那么watched_keys字典存储的数据大概如下:

Redis系列(九):Redis的事务机制

如果此时客户端3执行了以下WATCH命令:

Redis系列(九):Redis的事务机制

那么watched_keys字典存储的数据就变为:

Redis系列(九):Redis的事务机制

3.2 监视机制的触发

那么问题来了,既然watched_keys字典存储了被WATCH命令监视的键,那么监视机制是如何被触发的呢?

答案是所有对数据库修改的命令,比如SETLPUSHSADD等,在执行之后都会对watched_keys字典进行检查,如果有客户端正在监视刚刚被命令修改的键,那么所有监视该键的客户端的REDIS_DIRTY_CAS标识将被打开,表示该客户端的事务安全性已经被破坏。

以上图为例,如果键“name”的值被修改,那么客户端1、客户端3的REDIS_DIRTY_CAS标识会被打开。

3.3 判断事务是否安全

最后非常关键的一步是,当服务器接收到一个客户端发来的EXEC命令时,服务器会根据这个客户端是否打开了REDIS_DIRTY_CAS标识来决定是否执行事务,判断的流程图如下所示:

Redis系列(九):Redis的事务机制

4. 事务执行失败举例

先来看第1个例子,这个事务因为命令入队出错被服务器拒绝执行,事务中的所有命令都不会被执行:

Redis系列(九):Redis的事务机制

再来看第2个例子,事务入队时出现了不存在的命令,服务器将拒绝执行这个事务:

Redis系列(九):Redis的事务机制

再来看第3个例子,RPUSH命令在执行期间报错了,但后续命令仍然继续执行,并且之前执行的命令没有受到任何影响:

Redis系列(九):Redis的事务机制

这个例子也说明Redis事务不支持回滚机制

5. 总结

Redis的事务提供了一种将多个命令打包,然后一次性、有序地执行的机制,

它的原理是多个命令会被入队到事务队列中,然后按先进先出(FIFO)的顺序执行,

并且事务在执行过程中不会被中断,当事务队列中的所有命令都被执行完毕之后,事务才会结束。

6. 参考

黄健宏 《Redis设计与实现》


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/7005.html

(0)
上一篇 2023-03-29
下一篇 2023-03-29

相关推荐

  • MySQL数据库设计规范

    MySQL数据库设计规范具体 小数类型 // 附录2 6. 【强制】小数类型为 decimal,禁止使用 float 和 double。 说明:在存储的时候,float 和 double 都存在精度损失的问题,很可能在比较…

    2023-03-27
    107
  • Cassandra 在 360 的实践与改进[通俗易懂]

    Cassandra 在 360 的实践与改进[通俗易懂]分享嘉宾:王锋 奇虎360 技术总监 文章整理:王彦 内容来源:Cassandra Meetup 出品平台:DataFunTalk 注:欢迎转载,转载请留言。 导读:2010年,Dropbox 在线云

    2023-01-31
    100
  • python文本词频统计_文本数据挖掘与python应用

    python文本词频统计_文本数据挖掘与python应用数据挖掘第三篇 文本分类 文本分类总体上包括8个步骤。数据探索分析 》数据抽取 》文本预处理 》分词 》去除停用词 》文本向量化表示 》分类器 》模型评估.重要python库包括numpy(数组),p

    2022-12-27
    96
  • redis 哨兵「建议收藏」

    redis 哨兵「建议收藏」哨兵作用 哨兵(sentinel) 是一个分布式系统,是程序高可用性的一个保障。用于监视任意多个主服务器,以及这些主服务器属下的所有从服务器,当出现故障时通过投票机制选择新的master并将所有sla

    2023-03-13
    91
  • Python数据类型:定义和应用

    Python数据类型:定义和应用Python是一种解释型、面向对象、动态数据类型的高级程序语言。Python数据类型分为数字、字符串、列表、元组、字典等。其中数字分为整数和浮点数两种,字符串是以单引号或双引号包含的字符序列,列表和元组是可以修改和不可修改的序列类型,字典是无序的键值对集合。

    2024-01-14
    53
  • redis 入门一「终于解决」

    redis 入门一「终于解决」一、redis 简介 1、什么是 redis? redis 是一个开源免费的高性能的 key – value 数据库。 支持数据持久化,即可以将内存的数据存储在磁盘中,重启服务后可以再次加载磁盘中的数

    2023-02-15
    116
  • Python程序暂停时间——time.sleep()

    Python程序暂停时间——time.sleep()时间是程序中一个非常重要的因素,能够在程序中实现暂停或延迟执行就显得尤为重要。Python的time模块提供了time.sleep()函数,让我们能够优雅地控制程序暂停时间。

    2024-03-20
    33
  • Python 正则表达式教程:精通匹配与替换技巧

    Python 正则表达式教程:精通匹配与替换技巧Python 正则表达式是一个强大的工具,它可以让我们在处理字符串时更加高效和灵活。Python 正则表达式可以用来匹配字符串、替换字符串、从字符串中提取关键信息等等。掌握 Python 正则表达式可以让我们在数据处理、爬虫、文本编辑等方面提高工作效率。

    2024-02-15
    48

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注