5.Redis事务和乐观锁操作

感谢秦疆老师的redis视频教程,更多了解哔哩哔哩搜索【狂神说Java】。

本文内容源于秦疆老师的redis视频教程。给狂神推荐,点赞吧!

Redis事务

Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!

一次性,顺序性,排他性!执行一些列的命令!

------队列 set set set 执行-------

Redis事务没有隔离级别的概念!

所有的命令在事务中,并没有直接执行!只有发起执行命令才会执行!Exec

Redis单条命令式保存原子性的,但是事务不保证原子性!

Redis的事务:

  • 开启事务(multi)
  • 命令入队{。。。 QUEUED}
  • 执行事务(exec)

正常执行事务!

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> set k3 v3
QUEUED
127.0.0.1:6379> exec #执行事务
1) OK
2) OK
3) "v2"
4) OK

放弃事务

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> set k4 v4
QUEUED
127.0.0.1:6379> discard #取消事务
OK
127.0.0.1:6379> get k4 #事务队列中命令都不会被执行
(nil)

编译型异常(Java中代码有问题!Redis中命令错误!),事务中所有的命令都不会执行。

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> set k3 v3
QUEUED
127.0.0.1:6379> getset k3 #错误的命令
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> exec #执行事务报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1 #所有的命令都不会执行
(nil)

运行时异常(就是语法错误,比如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> set k3 v3
QUEUED
127.0.0.1:6379> get k3
QUEUED
127.0.0.1:6379> exec
1) (error) ERR value is not an integer or out of range #虽然第一条命令出错了,但是依旧正常执行成功!
2) OK
3) OK
4) "v3"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k1
"v1"

Redis乐观锁操作

监控!Watch

悲观锁

  • 很悲观,认为什么时候都会出现问题,无论做什么都会加锁!

乐观锁

  • 很乐观,认为什么时候都不会出错,所以不会上锁!
  • 获取version
  • 更新时候比较版本号

类似数据库version:

update goods set status=2,version=version+1

where id=#{id} and version=#{version};

Redis监视测试!watch

正常执行成功

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money #监视 money 对象
OK
127.0.0.1:6379> multi #事务正常结束,数据期间没有发生变动,这个时候就可以执行
OK
127.0.0.1:6379> DECRBY money 20
QUEUED
127.0.0.1:6379> INCRBY out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20


  • 测试多线程修改值,使用watch可以当做redis的乐观锁来操作

另外开启一个redis事务:

在这里插入图片描述

127.0.0.1:6379> watch money # 监视 money
OK
127.0.0.1:6379> multi 
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
127.0.0.1:6379> exec #执行之前,另一个线程,修改了我们的值,这个时候,就会导致事务执行失败!
(nil)

在这里插入图片描述

  • 如果修改失败,获取最新的值就好
127.0.0.1:6379> unwatch
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 1
QUEUED
127.0.0.1:6379> INCRBY out 1
QUEUED
127.0.0.1:6379> exec
1) (integer) 59
2) (integer) 31
posted @ 2020-05-16 17:46  我有满天星辰  阅读(2)  评论(0编辑  收藏  举报