[Redis][19][事务]

SpringCloud项目实战:Camunda7.19工作流审批集成避坑指南(附完整配置流程) 本文详细介绍了SpringCloud与Camunda7.19工作流引擎的深度整合实战,包括版本兼容性、数据库配置、微服务架构设计、审批流业务建模及生产环境调优等关键环节。特别针对审批流程中的常见陷阱提供了避坑指南,并附有完整配置流程,助力开发者高效实现复杂审批系统的集成与优化。 阅读详情

第 19 章 事务

Redis通过MULTIEXECWATCH等命令来实现事务功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求。

以下是一个事务执行的过程,该事务首先以一个MULTI命令为开始,接着将多个命令放入事务当中,最后由EXEC命令将这个事务提交给服务器执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
redis> MULTI
OK

redis> SET "name" "Practical Common Lisp"
QUEUED

redis> GET "name"

redis> SET "author" "Peter Seibel"
QUEUED

redis> GET "author"
QUEUED

redis> EXEC
1) OK
2) "Practical Common Lisp"
3) OK
4) "Peter Seibel"

19.1 事务的实现

一个事务从开始到结東通常会经历以下三个阶段

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

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

MULTI命令可以将执行该命令的客户端从非事务状态切换至事务状态,这一切换是通过在客户端状态的flags属性中打开REDIS MULTI标识来完成的,如下伪代码

1
2
3
4
5
6
7
def MULTI():

    # 打开事务标志
    client.flags |= REDIS_MULTI

    # 返回OK回复
    replyOK()
19.1.2 命令入队

当一个客户端处于非事务状态时,这个客户端发送的命令会立即被服务器执行,当一个客户端切换到事务状态之后,则不一定,它会根据不同的命令见机行事:

  • 如果客户端发送的命令为EXECDISCARDWATCHMULTI四个命令的其中一个,那么服务器立即执行这个命令。
  • 与此相反,如果客户端发送的命令是EXECDISCARDWATCHMULTI四个命令以外的其他命令,那么服务器并不立即执行这个命令,而是将这个命令放入一个事务队列里面,然后向客户端返回QUEUED回复。

如下流程图所示

19.1.3 事务队列

每个Redis客户端都有自己的事务状态,这个事务状态保存在客户端状态的mstate属性中,它包括一个事务队列和一个已入队命令的计数器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef struct redisClient{
    //...

    //事务状态
    multiState mstate;

    //...
}
typedef struct multiState{

    //事务队列,FIFO顺序
    multiCmd *command;

    //已入队命令计数
    int count;
}multiState;

事务队列以先进先出的方式保存入队的命令,较先人队的命令会被放到数组的前面,而较后入队的命令则会被放到数组的后面,例如下图

19.1.4 执行事务

当一个处于事务状态的客户端向服务器发送EXEC命令时,这个EXEC命令将立即被服务器执行。服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令所得的结果全部返回给客户端

EXEC命令的伪代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def EXEC()
    # 创建空白的回复队列
    reply_queue = []
    
    # 遍历事务队列中的每个项
    # 读取命令的参数,参数的个数,以及要执行的命令
    for argv, argc, cmd in client.mstate.commands:
    
        # 执行命令,并取得命令的返回值
        reply = execute_command(cmd, argv, argc)

        # 将返回值追加到回复队列末尾
        reply_queue.append(reply)

    # 移除REDIS_MULTI标识,让客户端回到非事务状态
    client.flags &= ~REDIS_MULTI
    
    # 清空客户端的事务状态,包括
    # 1)清零入队命令计数器
    # 2)释放事务队列
    
    client.state.count = 0
    release_transaction_queue(client.mstate.commands)
    
    # 将事务的执行结果返回给客户端
    send_reply_to_client(client, reply_queue)

19.2 WATCH命令的实现

WATCH命令是一个乐观锁,它可以在EXEC命令执行之前,监视任意数量的数据库键,并在EXEC命令执行时,检查被监视的键是否至少有一个已经被修改过了,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复。

1
redis> WATCH "name"
19.2.1 使用WATCH命令监视数据库键

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

1
2
3
4
5
6
7
8
typedef struct redisDb{
    //...

    //正在被WATCH命令监视的键
    dict *watched_keys

    //...
} redisDb;

通过watched_keys字典,服务器可以清楚地知道哪些数据库键正在被监视,以及哪些客户端正在监视这些数据库键。

下图就是一个watched_keys字典的例子

19.2.2 监视机制的触发

所有对数据库进行修改的命令,在执行之后都会调用multi.c/touchWatchKey函数对watched_keys字典进行检查,查看是否有客户端正在监视刚刚被命令修改过的数据库键,如果有的话,那么touchWatchKey函数会将监视被修改键的客户端的REDIS_DIRTY_CAS标识打开,表示该客户端的事务安全性已经被破坏。

伪代码描述如下

1
2
3
4
5
6
7
8
9
10
def touchWatchKey(db, key):
    # 如果键key存在于数据库的watched_keys字典中
    # 那么说明至少有一个客户端在监视这个key
    if key in db.watched_keys:

        # 遍历所有监视键key的客户端
        for client in db.watched_keys[key]

            # 打开标志
            client.flags |= REDIS_DIRTY_CAS
19.2.3 判断事务是否安全

当服务器接收到一个客户端发来的EXEC命令时,服务器会根据这个客户端是否打开了REDIS_DIRTY_CAS标识来决定是否执行事务:

19.3 事务的ACID性质

在Redis中,事务总是具有原子性、一致性和隔离性,并且当Redis运行在某种特定的持久化模式下时,事务也具有耐久性

19.3.1 原子性

对于Redis的事务功能来说,事务队列中的命令要么就全部都执行,要么就一个都不执行,因此,Redis的事务是具有原子性的。

Redis的事务和传统的关系型数据库事务的最大区别在于,Redis不支持事务回滚机制,即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止

19.3.2 一致性

事务具有一致性指的是,如果数据库在执行事务之前是一致的,那么在事务执行之后,无论事务是否执行成功,数据库也应该仍然是一致的。

19.3.3 隔离性

事务的隔离性指的是,即使数据库中有多个事务并发地执行,各个事务之间也不会互相影响,并且在并发状态下执行的事务和串行执行的事务产生的结果完全相同。

因为Redis使用单线程的方式来执行事务,并且服务器保证,在执行事务期间不会对事务进行中断,因此,Redis的事务总是以串行的方式运行的,并且事务也总是具有隔离性的。

19.3.4 耐久性

只有当服务器运行在AOF持久性模式下,并且appendfsync选项的值为always时,程序总会在执行命令之后调用同步函数,将命令数据真正的保存到硬盘里面,因此这种配置下的事务是具有耐久性的

Turbo Intruder 1.0.19 实战:3类业务并发漏洞(点赞/验证码/代金券)测试与修复 本文详细介绍了使用Turbo Intruder 1.0.19进行三类业务并发漏洞(点赞/验证码/代金券)的测试与修复方法。通过实战案例演示了漏洞原理、测试步骤及修复方案,帮助开发者识别和防范高危害性的并发漏洞,提升Web应用安全性。 阅读详情

相关推荐

Redis设计与实现》第19事务

19章 事务 Redis通过MULTI、EXEC、WATCH等命令来实现事务(transaction)功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求。 以下是一个事务执行的过程,该事务首先以一个MULTI命令为开始,接着将多...

jxgy01的博客 153

Redis的各种机制

一、Redis的持久化机制 1.简介 Redis有两种持久化机制,分别是RDB和AOF,RDB:每个一段时间保存一个快照;AOF:保存每次写的操作指令; 2.RDB (1)RDB的概念 RDB:每隔一段时间,把内存中的数据写入磁盘的临时文件,作为快照,恢复的时候把快照文件读进内存。如果宕机重启,那么内存里的数据肯定会没有的,因为RDB的存在,那么重启redis后,则会恢复。 (2)备份与恢复 备份:内存备份 --> 磁盘临时文件 恢复:磁盘临时文件 --> 恢复到内存 (3)RDB优劣势分析 优

qq_42282792的博客 1356

InternVL 3.5 深度解析:开源多模态模型的新里程碑

InternVL 3.5是由上海人工智能实验室OpenGVLab团队推出的开源多模态大模型,在推理能力、效率和灵活性方面取得突破。该模型采用ViT-MLP-LLM架构,包含60亿参数的InternViT-6B视觉编码器和多种规格的语言模型骨干。核心创新包括:1)Cascade RL强化学习框架,通过离线热身和在线强化两阶段训练提升推理能力;2)ViR视觉分辨率路由器,动态调整图像处理分辨率以优化计算效率;3)DvD动态视觉token压缩技术。模型系列涵盖2B到241B参数规模,满足从边缘设备到高性能计算的不

m0_47999117的博客 972

redis19)--事务

目录 事务实现 事务开始 命令入队 事务队列 执行事务 WATCH命令 WATCH 命令的实现 WATCH 的触发 事务是否安全 事务的ACID性质 原子性 一致性 入队错误 执行错误 Redis 进程被终结 隔离性(Isolation) 持久性(Durability) Redis 通过 MULTI 、 DISCARD 、 EXEC 和 WATCH 四个命令来实...

demon7552003的小本本 271

Redis19Redis事务支持是如何实现的?

本文介绍了如何在Java中使用Jedis库实现Redis事务操作。主要内容包括:1) Jedis库的简介和Maven依赖配置;2) 基本事务操作的实现示例,展示multi/exec的使用;3) 使用WATCH命令实现乐观锁机制;4) 处理键冲突的示例代码和重试机制。文章还强调了Redis事务的注意事项,如命令执行顺序、缺乏回滚机制以及性能影响。通过Jedis可以方便地在Java应用中实现Redis事务功能,确保操作的原子性和一致性。

qq_43012298的博客 680

Redis 19 事务

Redis通过MULTI、EXEC、WATCH等命令来实现事务(transaction)功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求。

kking_edc的博客 336

2023.1.19 关于 Redis 事务详解

Redis 事务对比 MySQL 事务 MySQL 事务 Redis 事务 Redis 事务原子性解释 Redis 事务详解 执行流程 典型使用场景 Redis 事务命令 WATCH 的使用 WATCH 实现原理 总结

weixin_63888301的博客 889

redis设计与实现》-19事务transaction

一 序     Redis 通过 MULTI 、 DISCARD 、 EXEC 和 WATCH 、UNWATCH 5个命令来实现事务功能, 本章首先讨论使用 MULTI 、 DISCARD 和 EXEC 三个命令实现的一般事务, 然后再来讨论带有 WATCH 的事务的实现,最后通过常见的 ACID 性质对 Redis 事务的安全性进行了说明。 二 事务       事务提供了一种“将多个命令...

bohu83的博客 417

Redis学习笔记——第19事务

使用multi命令开启一个事务通过修改客户端的flags字段为REDIS_MULTI。

Lchen_kk的博客 470

redis设计与实现》第四部分 (第19事务

19 事务 Redis通过MULTI、EXEC、WATCH等命令来实现事务功能。 基本概念:事务提供了一种将多个命令请求打包,然后一次性按顺序执行多个命令的机制,在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后再去处理其他客户端的命令请求。 执行过程:事务首先以MULTI命令为开始,接着将多个命令放入事务当中,最后由EXEC命令将事务提交给服务器执行 19.1 事务的实现 经历三个阶段:事务开始、命令入队、事务执行 19.1.1 事务开始 M

快乐划水程序猿的专栏 345

redis学习笔记(19)---事务

事务的性质ACID  一般数据库的事务需要满足ACID四条性质:    redis事务   为了保持简单,redis事务保证了其中的一致性和隔离性;   不满足原子性和持久性;   1)原子性:redis事务在执行的中途遇到错误,不会回滚,而是继续执行后续命令;(违反原子性)   2)持久性:事务不过是用队列包裹起了一组 Redis 命令,并没有提供任何额外的持久性功能   Redis 事务可以

qinm的专栏 610

火影推荐程序连载19-Redis的基础事务和常用操作

Redis的基础事务和常用操作 和其他大部分的 NoSQL 不同,Redis 是存在事务的,尽管它没有数据库那么强大,但是它还是很有用的,尤其是在那些需要高并发的网站当中。 使用 Redis 读/写数据要比数据库快得多,如果使用 Redis 事务在某种场合下去替代数据库事务,则可以在保证数据一致性的同时,大幅度提高数据读/写的响应速度。互联网系统面向的是公众,很多用户同时访问服务器的可能性很大,尤其在一些商品抢购、抢红包等场合,对性能和数据的一致性有着很高的要求,而存储系统的读/写响应速度对于这类场景的

li123128的博客 254

【大白话说Java面试题 第183题】【07_Redis篇】第19题:Redis 事务是否具有 ACID 4 个特性?

本文从ACID四大特性的角度分析Redis事务的实现原理,逐一讲解Redis事务对原子性、一致性、隔离性、持久性的支持情况,对比Redis事务与关系型数据库事务的差异,同时介绍Lua脚本在Redis事务场景中的优势与适用场景,帮助读者正确理解Redis事务的能力边界。

AI工程硬核派+电脑生活效率咖 284

【分布式事务】DTM源码解析【更新中】

DTM是一个基于Go语言的分布式事务管理框架,支持SAGA、TCC、XA等多种事务协议。其核心思想是将长事务拆分为多个短事务,通过状态机和重试机制确保最终一致性。SAGA通过正向操作与补偿操作实现事务回滚,TCC采用Try-Confirm-Cancel三阶段提交,XA则依赖数据库原生XA接口实现两阶段提交。DTM提供统一API进行事务编排,支持HTTP/gRPC调用,具备灵活的事务协调和失败回滚能力,适用于微服务架构下的复杂事务场景。

王大阳的博客 95

2021年2月18日至2021年19日面经汇总

2021年2月18日至2021年19日面经汇总2021年2月18日至2021年19日面经汇总字节后端开发日常实习一二面面经进程和线程的区别线程在调度的时候应该如何同步死锁产生的原因内存的分配方式(这个问题我答的不是很流畅 但是尽可能在我知道的范围内答) 面试官还安慰我没事没事tcp/ip的五层模型输入一个链接 网页显示的过程是什么tcp的三次握手断开的时候tcp的四次挥手给定数组 乱序 找出数组中所有比左边的所有数大且比右边的所有数小的数字 第一个和最后一个不包括在内数据库模式 表 数据库里的表是应该怎么设

匿迹 409

Redis事务

Redis事务简介应用场景 Redis 事务可以一次执行多个命令,(按顺序地串行化执行,执行中不会被其它命令插入,不许加塞) 简介 Redis 事务可以一次执行多个命令(允许在一次单独的步骤中执行一组命令), 并且带有以下两个重要的保证: 批量操作在发送 EXEC 命令前被放入队列缓存。 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败, 其余的命令依然被执行。 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。 Redis会将一个事务中的所有命令序列化,然后按顺序执行 执

Hello World 258

电商系统防超卖全攻略:从Javashop压测看Redis分布式锁的实战优化

本文深入探讨电商系统防超卖的实战优化方案,以Javashop百万级并发压力测试为例,详细解析Redis分布式锁的技术细节与性能优化。通过基础版SETNX、进阶版红锁算法及Javashop的50ms极致优化方案,实现高并发下的库存精准控制,为开发者提供可直接落地的解决方案。

u6v7w8x的博客 716

2026最全Java高频面试题及答案

本文汇总了Java开发者常见的208道面试题,涵盖19个核心模块:Java基础、容器、多线程、反射、对象拷贝、JavaWeb、异常、网络、设计模式、Spring框架系列、Hibernate、Mybatis、消息队列(RabbitMQ/Kafka)、Zookeeper、MySQL、Redis及JVM等。内容包含基础概念辨析(如JDK/JRE区别)、核心原理(HashMap实现)、框架特性(Spring事务隔离)以及系统设计(Redis分布式锁)等高频考点。既适合求职者系统复习,也可供面试官参考。文章提供了完整

2401_89221445的博客 1510

CesiumJS 物种分布可视化实操手册:5步把生物多样性数据画到3D地球上

一份物种观测清单加一个保护区边界文件,放到3D地球上按时间轴动起来——这是 CesiumJS 物种分布可视化 最典型的落地场景。下面按一个真实任务走:从克隆项目开始,到把边界画上去、把点位标出来、把时间轴跑起来,最后把性能调顺。每一步你都能立刻在自己的机器上复现。 [![CesiumJS 3D地球地形渲染](https://raw.gitcode.com/GitHub_Trending/ce/c

gitblog_00239的博客 409
上一篇: [github][3][了解githubflow]
下一篇: [算法导论][7][快速排序]
TOUGH6
博客等级 码龄9年 2粉丝 111原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值