Redis 基本事务操作
Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程的中,会按照顺序执行!
Redis事务是一组Redis命令的有序集合,这些命令在事务中按照顺序执行,但在事务执行过程中不会立即执行,而是将它们放入一个队列中,等待显式提交(EXEC命令)后才会执行。
例如:(按顺序执行)执行一系列的命令!
------队列set set set执行------
Redis事务的特性:一次性、顺序性、排他性!(十分确定的特性)
Redis事务没有没有隔离级别的概念!
所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行!
Redis单条命令式保存原子性的,但是事务不保证原子性!
原子性(Atomicity):Redis事务中的所有命令要么全部执行成功,要么全部执行失败,这保证了事务的原子性,不会出现部分执行成功或部分执行失败的情况。Redis单条命令式保存原子性的,但是事务不保证原子性!
隔离性(Isolation):Redis事务在执行期间对其他客户端是不可见的。在一个事务执行过程中,其他客户端不能访问其中的数据,只有当事务提交后,其他客户端才能看到事务所做的修改。Redis事务没有没有隔离级别的概念!所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行!
一致性/一次性(Consistency):Redis事务在执行前会检查事务队列中的所有命令是否合法,如果有任何一个命令不合法(如语法错误),整个事务都不会执行。
持久性(Durability):Redis事务在提交后会将执行结果持久化到磁盘,以确保数据的持久性。
顺序性(Sequence):Redis事务是串行执行的,事务队列中的命令按照顺序依次执行,不会出现并发冲突。
回滚(Rollback):Redis事务可以使用DISCARD命令进行回滚,如果在事务执行过程中发生错误或需要取消事务,可以使用DISCARD命令撤销事务中的所有命令,使事务不产生任何影响。
需要注意的是,虽然Redis事务具有原子性和一致性的特性,但不支持事务中的回滚(ROLLBACK)操作。因此,一旦事务执行成功,就无法撤销其中的修改。此外,Redis事务不同于关系型数据库中的事务,它不提供锁定机制或隔离级别,因此需要开发者自行确保数据的一致性和并发控制。
Redis的事务∶
开启事务(MULTI)
命令入队(.......)
执行事务(EXEC)
执行事务!
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>
放弃事务!
127.0.0.1:6379> mu7ti #开启事务
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 #事务队列中命令都不会被执行!
(ni1)
编译型异常(代码有问题!命令有错!),事务中所有的命令都不会被执行!
运行时异常(1/0),如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常!
因此我们可以认为当出现编译型异常的时候Redis事务会取消执行,但是遇到运行时错误的时候Redis事务会继续执行。
什么是悲观锁,什么是乐观锁?
悲观锁:很悲观,认为什么时候都会出问题,无论做什么都会加锁!
乐观锁:很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据。
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 # 减少 money 20
QUEUED
127.0.0.1:6379> INCRBY out 20 #添加 out 20
QUEUED
127.0.0.1:6379>exec
1) (integer) 80
2) (integer) 20
测试多线程修改值,使用watch可以当做redis的乐观锁操作!(使用watch监控设定的值到底有没有在我事务发生的过程中发生变化,如果发生变化了,就会导致事务执行失败)
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 #执行之前,另外一个线程,修改了我们的值,这个时候,就会导致事务执行失败!(ni1)
如何重新运行该事务呢,如下所示(我们可以先取消监控,之后监控最新的值即可)