📢📢📢📣📣📣?
哈喽!大家好,我是【一心同学】,一位上进心十足的【Java领域博主】!😜😜😜
?【一心同学】的写作风格:喜欢用【通俗易懂】的文笔去讲解每一个知识点,而不喜欢用【高大上】的官方陈述。
?【一心同学】博客的领域是【面向后端技术】的学习,未来会持续更新更多的【后端技术】以及【学习心得】。
?如果有对【后端技术】感兴趣的【小可爱】,欢迎关注【一心同学】💞💞💞
??????感谢各位大可爱小可爱!???????
目录
一、Redis事务介绍
二、Redis事务三大保证
三、基本命令
四、场景演示
🌴 正常执行事务
🌴 取消事务
🌵 编译型异常
🌵 运行时异常
五、监控
🌴 正常执行场景
🌵 异常执行
小结
一、Redis事务介绍
在关系型数据库中的事务是原子性的,但作为非关系型数据库的Redis的事务是非原子性的,原子性就是整个程序中的所有操作,要么全部完成,要不全部不完成。也就是说在我们的Redis事务中,我们执行了操作A,操作B,如果操作A失败,另一个表仍然会继续执行,事务不会回滚(对于关系型数据库不会出现非原子性)。
一个事务从开始到执行会经历以下三个阶段:
二、Redis事务三大保证
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证: (1)批量操作在发送 EXEC 命令前被放入队列缓存。 (2)收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。(除了编译型异常) (3)在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
🔥?注意
🚀?Redis事务没有没有隔离级别的概念。
🚀?所有的命令在事务中,并没有直接被执行,只有发起执行命令Exec的时候才会执行。
🚀?Redis单条命令式保存原子性的,但是事务不保证原子性。
三、基本命令
序号 | 命令及描述 |
---|
1 | ?DISCARD 取消事务,放弃执行事务块内的所有命令。? | 2 | ?EXEC 执行所有事务块内的命令。? | 3 | ?MULTI 标记一个事务块的开始。? | 4 | ?UNWATCH 取消 WATCH 命令对所有 key 的监视。? | 5 | ?WATCH key [key ...] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。? |
四、场景演示
🌴 正常执行事务
127.0.0.1:6379> multi #开启事务
OK
#命令入队
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec #执行事务
1) OK
2) OK
3) "v2"
🌴 取消事务
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> discard #取消事务
OK
127.0.0.1:6379> get k1 #事务队列中命令都不会被执行
(nil)
🌵 编译型异常
Tip:代码或命令行写错,事务中的所有命令都不会执行。
127.0.0.1:6379> multi #开启事务
OK
#命令入队
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> getxxx k3 #错误命令
(error) ERR unknown command `getxxx`, with args beginning with: `k3`,
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> exec #执行事务报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k4 #所有的命令都不会被执行
(nil)
🌵 运行时异常
Tip: 例如1/0这种错误,如果事务队列中某个操作存在运行时异常问题,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常。
127.0.0.1:6379> set k1 'v1'
OK
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> incr k1 #对字符串执行自增操作
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec #执行事务
#虽然第一条命令报错了,但是依旧正常执行成功
1) (error) ERR value is not an integer or out of range
2) OK
3) "v2"
五、监控
Tip:进行监控一个数据,一直到事务结束,如果这个数据没有被其它线程改动,那么就执行成功。
🌴 正常执行场景
我们来模拟一个转账的例子,yixin向zhangsan转账20块。
127.0.0.1:6379> set money_yixin 100
OK
127.0.0.1:6379> set money_zhangsan 50
OK
127.0.0.1:6379> watch money_yixin #监控money_yixin这个对象
OK
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> decrby money_yixin 20
QUEUED
127.0.0.1:6379> incrby money_zhangsan 20
QUEUED
127.0.0.1:6379> exec #在这个事务期间,money_yixin的数据没有被其它线程影响到,执行成功。
1) (integer) 80
2) (integer) 70
🌵 异常执行
Tip:当我们所要监控的数据被其它线程修改了,那么在这个事务就无法正常执行。
线程一:
127.0.0.1:6379> set money_yixin 100
OK
127.0.0.1:6379> set money_zhangsan 50
OK
127.0.0.1:6379> watch money_yixin #监控money_yixin
OK
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> decrby money_yixin 20
QUEUED
127.0.0.1:6379> incrby money_zhangsan 20
QUEUED
注意:这个时候我们还没提交,我们进入第二个线程对money_yixin进行修改。
线程二:
127.0.0.1:6379> get money_yixin #此时线程一的事务还没执行,所有还是100
"100"
127.0.0.1:6379> decrby money_yixin 30 #对被监控的数据进行修改
(integer) 70
那么这个时候我们对线程一进行事务执行操作,由于线程二修改了我们监控的值,所以会导致事务执行失败!
解决方案:
对于这种情况,我们需要先使用命令UNWATCH进行解除监控,获取最新的值再次监控即可。
127.0.0.1:6379> unwatch #解除监控,获取最新数据
OK
127.0.0.1:6379> watch money_yixin
OK
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> decrby money_yixin 20
QUEUED
127.0.0.1:6379> incrby money_zhangsan 20
QUEUED
127.0.0.1:6379> exec #执行事务
1) (integer) 50
2) (integer) 70
?现在,请让【一心同学】扔出一张图,看完相信大家就能够清楚Redis中的事务操作了!
小结
以上就是【一心同学】对【Redis】中的【事务操作】讲解了,我们要记住【Redis】中的事物操作是【非原子性】的,这个概念【非常重要】,大家也可以自动动手跟着【一心同学】的思路敲一遍代码,相信就能更快的理解了。
如果这篇【文章】有帮助到你,希望可以给【一心同学】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【后端技术】感兴趣的小可爱,也欢迎关注???????【一心同学】??????,我将会给你带来巨大的【收获与惊喜】💕💕!
|