事务
所谓的事务就是很多命令一连串的执行
*Redis的事务不保证原子性,并且不具有隔离级别(隔离性),但是Redis的单个命令保持原子性。
*Redis的所有事务并不是直接被执行,是在发起执行命令后才会执行。
Redis事务的生命周期
1、开启事务(Multi)
#例子:
127.0.0.1:6379>multi #开启事务
ok #代表事务开启成功
2 、命令入队(任意命令)
#例子:
127.0.0.1:6379>multi #开启事务
OK #表示开启事务成功
127.0.0.1:6379>set user:1 name zhangsan age 18 #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>set user:2 name lisi age 20 #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>get user:2 name age #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>
3、执行事务(exec)
#例子:
127.0.0.1:6379>multi #开启事务
OK #表示开启事务成功
127.0.0.1:6379>set user:1 name zhangsan age 18 #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>set user:2 name lisi age 20 #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>get user:2 name age #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>exec
1)OK
2)OK
3)lisi 20
Redis有操作事务,同样也有取消事务,命令为:Discard
取消事务后,事务队列中的命令全部失效。
#例子:
127.0.0.1:6379>multi #开启事务
OK #表示开启事务成功
127.0.0.1:6379>set user:1 name zhangsan age 18 #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>set user:2 name lisi age 20 #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>get user:2 name age #任意命令
QUEUED #表示入队成功
127.0.0.1:6379>Discard
127.0.0.1:6379>OK
异常
1、编译时异常
在redis事务中,在你命令编写错误时,开启事务,整个事务队列的命令全部不会执行。
2、运行时异常
在redis事务中,命令没有问题的情况下开启事务,运行时异常了也会接着执行。
事务监控
乐观锁(watch)
乐观锁,代表很“乐观”,在访问时总是假设不会出现问题,但是,在访问时都会判断其他人有没有修改这条数据,可以使用版本号机制和CAS算法实现。
悲观锁
悲观锁,代表很“悲观”,在任何一个用户访问时都会觉得其他用户都会修改数据,然后会拿到锁把事务锁上,其他用户只能在前一个用户释放锁的时候继续拿锁进行任务处理。
举例:
在正常情况(单线程)下,我有100块钱(money),我花了20块钱(out)
127.0.0.1:6379>set money 100 #表示我有100块钱
127.0.0.1:6379>set out 0 #out当前备用
127.0.0.1:6379>watch money #监听指定元素,监听效果,判断当前取到的数据是否与真正的值相同
127.0.0.1:6379>multi #开启事务
OK #开启事务成功
127.0.0.1:6379>decrby money 20 #我花钱给out -20
QUEUED #表示入队成功
127.0.0.1:6379>incrby out 20 #赚到20 +20
QUEUED #表示入队成功
127.0.0.1:6379>get money
QUEUED #表示入队成功
127.0.0.1:6379>get out
QUEUED #表示入队成功
127.0.0.1:6379>exec
3)OK
4)OK
5)(integer)80
6)(integer)20
在不正常情况(2到多个线程),我有100块钱(money),我花了20块钱(out),但是还在我第一条线程事务还没执行时,另一条线程把我们的money修改了 , 我们配置的的watch(监听)money这个时候就会发现数据不一致,导致事务返回null
举例:
第一个用户
127.0.0.1:6379>set money 100 #表示我有100块钱
127.0.0.1:6379>set out 0 #out当前备用
127.0.0.1:6379>watch money #监听指定元素,监听效果,判断当前取到的数据是否与真正的值相同
127.0.0.1:6379>multi #开启事务
OK #开启事务成功
127.0.0.1:6379>decrby money 20 #我花钱给out -20
QUEUED #表示入队成功
127.0.0.1:6379>incrby out 20 #赚到20 +20
QUEUED #表示入队成功
127.0.0.1:6379>get money
QUEUED #表示入队成功
127.0.0.1:6379>get out
#**************************还没开启之前第二个线程修改了数据*******************************
QUEUED #表示入队成功
127.0.0.1:6379>exec
#******************启动事务,查看返回结果,监听到money已经被改变,获取不到******************
(nul)
第二个用户(在第一个用户执行事务之前的操作)
127.0.0.1:6379>get money
(integer)100
127.0.0.1:6379>set money 200
OK
127.0.0.1:6379>get money
(integer)200