请你谈谈Redis事务的理解?

Redis事务本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行 。事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行——Redis没有原子性,Redis单条命令保证原子性,但是事务不保证原子性Redis事务没有隔离级别的概念。所有的命令在事务中,并没有被直接被执行,只有发起执行命令的时候才会被执行——Exec。
Redis事务的三个阶段:1开启事务(multi) 2命令入队(……) 3执行事务(exec);

0Redis事务相关命令

Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的;1 redis 不支持回滚——Redis 在事务失败时不进行回滚,而是继续执行余下的命令, 所以 Redis 的内部可以保持简单且快速;如果在一个事务中的命令出现编译错误,那么所有的命令都不会执行;如果在一个事务中出现运行错误,那么正确的命令会被执行。

WATCH 命令是一个乐观锁,可以为 Redis 事务提供CAS行为。 可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。

命令特点
MULTI命令用于开启一个事务,它总是返回OK ,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行
EXEC执行所有事务块内的命令 ,返回事务块内所有命令的返回值,按命令执行的先后顺序排列, 当操作被打断时,返回空值 nil
DISCARD客户端可以清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出
UNWATCH取消watch对所有key的监控

1事务管理(ACID)概述

Redis的事务总是具有ACID中的一致性和隔离性,其他特性是不支持的。Redis单条命令保证原子性,但是事务不保证原子性。

2监控!Watch 面试常问

https://blog.csdn.net/zs18753479279/article/details/115616451

悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加 version 来获取数据,性能较悲观锁有很大的提高。

正常执行成功

watch key # 监视值

unwatch # 放弃监视

exec	# 执行事务

multi	# 开启事务


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的乐观锁操作

# 主线程
127.0.0.1:6379> watch 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)

# 线程2
127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1000
OK

在这里插入图片描述

3乐观锁控制事务

大多是基于数据版本的记录机制。什么是数据版本?就是为数据增加一个版本标识,即为数据库表添加一个version字段,当读取数据时,把数据库版本一同读出,当做了修改后,将数据库版本+1,同修改一起提交。如果提交数据的版本号 >数据库当前版本号,提交成功。如图:
在这里插入图片描述

4事务实操

1正常执行事务

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

2放弃事务

事务中的命令都不会被执行

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)

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

所有的命令都不会被执行

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v2 
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> set k5 v5
QUEUED
127.0.0.1:6379> exec	# 执行事务报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k5	# 所有的命令都不会被执行
(nil)

4运行时异常(1/0),如果事务队列中存在语法性错误,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 "v1"
QUEUED
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) OK
2) (error) ERR value is not an integer or out of range  # 虽然这条命令报错,但是依旧执行成功
3) OK
4) OK
5) "v3"
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值