Redis 13 事务
参考源
https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0
版本
本文章基于 Redis 6.2.6
概述
Redis 事务的本质是一组命令的集合
事务支持一次执行多个命令,一个事务中所有命令都会被序列化。
在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
所以说:Redis 事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。
Redis 事务没有隔离级别的概念
批量操作在发送 EXEC
命令前被放入队列缓存,并不会被实际执行。
Redis 事务不保证原子性
Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。
事务中任意命令执行失败,其余的命令仍会被执行。
Redis事务的三个阶段
开始事务
命令入队
执行事务
命令
监听
watch
watch key1 key2 ...
监视一或多个 key,如果在事务执行之前,被监视的 key 被其他命令改动,则事务被打断(类似乐观锁)。
取消监听
unwatch
取消对所有 key 的监控。
标记
multi
标记一个事务块的开始,形成队列(queued)。
执行
exec
执行所有事务块(一旦执行 exec
后,之前加的监控锁都会被取消掉)。
取消
discard
取消事务,放弃事务块中的所有命令。
实践
正常执行
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379(TX)> set k1 v1 # 命令入队
QUEUED
127.0.0.1:6379(TX)> set k2 v2 # 命令入队
QUEUED
127.0.0.1:6379(TX)> get k2 # 命令入队
QUEUED
127.0.0.1:6379(TX)> set k3 v3 # 命令入队
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务
1) OK
2) OK
3) "v2"
4) OK
127.0.0.1:6379> get k1 # set命令执行成功
"v1"
127.0.0.1:6379> get k2 # set命令执行成功
"v2"
开启事务后,会出现 TX 标志,此时所有的操作不会马上有结果,而是形成队列(QUEUED),待执行事务后,会将所有命令按顺序执行。
放弃事务
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379(TX)> set k1 v1 # 命令入队
QUEUED
127.0.0.1:6379(TX)> set k2 v2 # 命令入队
QUEUED
127.0.0.1:6379(TX)> set k3 33 # 命令入队
QUEUED
127.0.0.1:6379(TX)> discard # 取消事务
OK
127.0.0.1:6379> get k3 # set命令未执行
"v3"
事务中存在命令性错误
若在事务队列中存在命令性错误(类似于java编译性错误),则执行 exec
命令时,所有命令都不会执行。
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379(TX)> set k1 11 # 命令入队
QUEUED
127.0.0.1:6379(TX)> getset k2 # 错误命令
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k2 22 # 命令入队
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务,报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1 # set命令未执行
"v1"
127.0.0.1:6379> get k2 # set命令未执行
"v2"
事务中存在语法性错误
若在事务队列中存在语法性错误(类似于 Java 的的运行时异常),则执行 exec
命令时,其他正确命令会被执行,错误命令抛出异常。
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379(TX)> set k4 v4 # 命令入队
QUEUED
127.0.0.1:6379(TX)> incr k4 # 命令入队(对“v4”进行 +1 ,会报语法错误)
QUEUED
127.0.0.1:6379(TX)> set k5 v5 # 命令入队
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务
1) OK
2) (error) ERR value is not an integer or out of range # 执行错误的命令会报错,其余命令正常执行
3) OK
127.0.0.1:6379> get k4 # set命令执行成功
"v4"
127.0.0.1:6379> get k5 # set命令执行成功
"v5"
监听
悲观锁
悲观锁(Pessimistic Lock),顾名思义,就是很悲观。
每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。
这样别人想拿到这个数据就会 block 直到它拿到锁。
传统的关系型数据库里面就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在操作之前先上锁。
乐观锁
乐观锁(Optimistic Lock),顾名思义,就是很乐观。
每次去拿数据的时候都认为别人不会修改,所以不会上锁。
但是在更新的时候会判断一下再此期间别人有没有去更新这个数据,可以使用版本号等机制。
乐观锁适用于多读的应用类型,这样可以提高吞吐量。
乐观锁策略:提交版本必须大于记录当前版本才能执行更新。
实践
初始化信用卡可用余额和欠额
127.0.0.1:6379> set balance 100
OK
127.0.0.1:6379> set debt 0
OK
使用 watch 监听 balance,事务期间 balance 数据未变动,事务执行成功。
127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby balance 20
QUEUED
127.0.0.1:6379(TX)> incrby debt 20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20
使用 watch 监听 balance,事务期间 balance 数据变动,事务执行失败。
窗口 1:
127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> multi
OK
窗口 2:
127.0.0.1:6379> get balance
"80"
127.0.0.1:6379> set balance 200
OK
窗口 1:
127.0.0.1:6379(TX)> decrby balance 20
QUEUED
127.0.0.1:6379(TX)> incrby detb 20
QUEUED
127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379> get balance
"200"
由于窗口 1 监听 balance 并开启事务后,窗口 2 修改了 balance 的值,导致窗口 1 的监听失败,执行事务后展示为空,且 balance 的值不是预期值。
监听失败后放弃监听,然后重来
窗口 1:
127.0.0.1:6379> unwatch
OK
127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby balance 20
QUEUED
127.0.0.1:6379(TX)> incrby debt 20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 180
2) (integer) 40
小结
一旦执行
exec
开启事务后,无论事务是否执行成功,watch
对变量的监听都将被取消。当事务执行失败后,需重新执行
watch
命令对变量进行监听,并开启新的事务进行操作。watch
指令类似于乐观锁,在事务提交时,如果watch
监控的多个 key 中任何 key 的值已经被其他客户端更改。则使用
exec
执行事务时,事务队列将不会被执行,同时返回 (nil) 应答以通知调用者事务执行失败。
Redis 13 事务的更多相关文章
- Redis保证事务一致性,以及常用的数据结构
reids命令可以参考中文官网:http://redis.cn/commands.html 关于reids的使用,可以封装到工具类进行调用: Redis的工具类:JedisAdapter 除了数据结构 ...
- 第四章· Redis的事务、锁及管理命令
一.事务介绍 二.Redis乐观锁介绍 三.Redis管理命令 一.事务介绍 Redis的事务与关系型数据库中的事务区别 1)在MySQL中讲过的事务,具有A.C.I.D四个特性 Atomic(原子性 ...
- Redis的事务
Redis对事务的支持是部分支持,不想oracle,要么都成功要么都失败,Redis可以部分成功部分失败 1 是什么: 可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺 ...
- Redis笔记(五)Redis的事务
>>关系型数据库的事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消. Atomic(原子性): 一个事务(transaction)中的 ...
- redis的事务(简单介绍)
1.简单描述 redis对事务的支持目前还是比较简单.redis只能保证一个client发起的事务中的命令是可以连续的执行,而中间不会插入其他client的命令.由于redis是但现场来处理所有cli ...
- Redis的事务功能详解
Redis的事务功能详解 MULTI.EXEC.DISCARD和WATCH命令是Redis事务功能的基础.Redis事务允许在一次单独的步骤中执行一组命令,并且可以保证如下两个重要事项: >Re ...
- Redis的事务和watch
redis的事务 严格意义来讲,redis的事务和我们理解的传统数据库(如mysql)的事务是不一样的. redis中的事务定义 Redis中的事务(transaction)是一组命令的集合. 事务同 ...
- spring中jedis对redis的事务使用注意总结
spring的@Transactional不支持redis的事务,并且redis的事务和其它关系型数据库的事务概念不是太一样,redis事务不支持回滚,并且一条命令出错后,后面的命令还会执行. 所以不 ...
- Redis(十一):Redis的事务功能详解
相关命令 1. MULTI 用于标记事务块的开始.Redis会将后续的命令逐个放入队列中,然后才能使用EXEC命令原子化地执行这个命令序列. 这个命令的运行格式如下所示: MULTI 这个命令的返回值 ...
随机推荐
- 哈工大软件构造Lab2(2022)
(防扒小助手) 本人CSDN博客: https://blog.csdn.net/m0_61753302https://blog.csdn.net/m0_61753302本人博客园博客(同步CSDN): ...
- SQL如何用表A更新表B
文章标题很短,因为问题的描述过于具体,标题就会显得过长. 这个问题更为准确地描述应该是这样:表结构雷同或者有相似字段的两张表A和B,如何用A表的字段数据去更新B表字段的数据? 操作方法: 1 upda ...
- python 的 @staticmethod和@classmethod和普通实例方法
参考:https://www.huaweicloud.com/articles/12607084.html https://blog.csdn.net/qq_30708445/article/deta ...
- 浏览器代理user-agent
两种方法: 法1:浏览器地址栏输入:about://version,然后复制用户代理: 如果法1不行,法2肯定可以. 法2:打开任意浏览器,输入任意网址,下面以火狐和百度网址为例来进行说明: 打开火狐 ...
- Arraylist集合、对象数组
Arraylist集合 ArrayList是List接口的一个实现类,它是程序中最常见的一种集合. 他的特点:在增加或删除指定位置的元素时,会创建新的数组,效率比较低,因此不适合做大量的增删操作,Ar ...
- Django从数据库导model迁移乱码
python manage.py inspectdb > [your app name]\models.py 执行后 model.py乱码,将models.py以 UTF-16LE打开.
- cve-2021-42287和cve-2021-42278漏洞复现
一.漏洞概述 cve-2021-42287 : 由于Active Directory没有对域中计算机与服务器账号进行验证,经过身份验证的攻击 者利用该漏洞绕过完全限制,可将域中普通用户权限提升为域管理 ...
- Metasploit msfvenom
一. msfvenom简介 msfvenom是msf payload和msf encode的结合体,于2015年6月8日取代了msf payload和msf encode.在此之后,metasploi ...
- zabbix实时监控mysql业务数据
1. 安装zabbix agent 下载zabbix:过往的软件包都有:https://sourceforge.mirrorservice.org/z/za/zabbix/ZABBIX%20Lates ...
- 数仓的字符截取三胞胎:substrb、substr、substring
摘要:下面就来给大家介绍这三个函数在字符截取时的一些用法与区别. 本文分享自华为云社区<GaussDB(DWS)中的字符截取三胞胎>,作者:我站在北方的天空下 . 在GaussDB(DWS ...