Redis事务
2023年3月15日00:06:36
一、redis的事务
redis事务特点
- redis单条命令是原子性操作
- redis事务本质是一组命令的集合
- redis事务不保证原子性
- 事务中所有的命令会被序列化,按照顺序执行
- 一次性、顺序性、排他性
- redis事务没有隔离级别
事务流程
- 开启事务(multi)
- 命令入队
- 执行事务(exec)
- 取消事务(discard)
#开启事务
127.0.0.1:6379[1]> multi
OK
#第一条命令
127.0.0.1:6379[1]> set name hyt
QUEUED
#第二条命令
127.0.0.1:6379[1]> set age 33
QUEUED
#第三条命令
127.0.0.1:6379[1]> get name
QUEUED
#第四条命令
127.0.0.1:6379[1]> del name
QUEUED
#执行事务,这时候才会将命令按照顺序执行
127.0.0.1:6379[1]> exec
1) OK
2) OK
3) "hyt"
4) (integer) 1
127.0.0.1:6379[1]> get name
(nil)
127.0.0.1:6379[1]> get age
"33"
事务异常
- 编译型异常:命令错误,在事务执行的时候直接报错,所有命令都不会执行
- 运行时异常:其他命令依然可以执行
#编译异常
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1]> set name hyt
QUEUED
#这条命令拼写错误
127.0.0.1:6379[1]> sett age 33
(error) ERR unknown command `sett`, with args beginning with: `age`, `33`,
127.0.0.1:6379[1]> get name
QUEUED
127.0.0.1:6379[1]> del name
QUEUED
#执行时候直接抛出异常,所有的命令都没有执行
127.0.0.1:6379[1]> exec
(error) EXECABORT Transaction discarded because of previous errors.
#运行时异常
127.0.0.1:6379[1]> multi
OK
#设置name = hyt
127.0.0.1:6379[1]> set name hyt
QUEUED
#设置自增,这里会异常因为name的值是字符串
127.0.0.1:6379[1]> decr name
QUEUED
127.0.0.1:6379[1]> set age 33
QUEUED
127.0.0.1:6379[1]> get name
QUEUED
127.0.0.1:6379[1]> get age
QUEUED
#执行事务发现第二条命令出现错误,但是后面的命令依然正常执行
127.0.0.1:6379[1]> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "hyt"
5) "33"
二、redis监控
锁
- 悲观锁
- 很悲观,认为什么时候都会出现问题,做任何操作都会加锁
- 乐观锁
- 很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据
- 获取version
- 更新的时候比较version
watch实现乐观锁
- watch在事务开启前启动监控
- 如果在事务执行前发现监控的值发生变化,事务将执行失败
- watch在事务执行之后,无论成功或者失败都会自动解除监控
- unwatch解除监控
###################################打开客户端1
#我们使用第一个客户端设置key fund的值为1300
5) "1300"
#客户端1开启监控 watch key
127.0.0.1:6379[1]> watch fund
OK
#客户端1开启事务
127.0.0.1:6379[1]> multi
OK
#fund-900
127.0.0.1:6379[1]> decrby fund 900
QUEUED
#fund+250
127.0.0.1:6379[1]> incrby fund 250
QUEUED
#查询结果
127.0.0.1:6379[1]> get fund
QUEUED
###################################打开客户端2
#在第一个客户端执行事务之前,开启第二个客户端
127.0.0.1:6379[1]> get fund
"1300"
#客户端2修改fund的值
127.0.0.1:6379[1]> set fund 9000
OK
###################################回到客户端1
#客户端1执行事务,发现执行失败了,因为使用watch对fund的值进行了监控,然后开启了事务,但是在事务执行之前,fund被其他客户端进行了修改,监控发现fund变化之后,执行事务失败,实现乐观锁
127.0.0.1:6379[1]> exec
(nil)
标签:,事务,127.0,fund,0.1,6379,QUEUED
From: https://www.cnblogs.com/hyt810/p/18242959