一、什么是原子性??
同时失败或者同时成功!!
理解如下:
原子性即是,A原有5块石头,B原有3块石头;现有如下操作:
A让C给予B一块石头,那么应该发生的事情有,A失去一块石头,变为4块,B得到一块石头变为5块;此时交易成功。
不排除有意外情况,比如C在给予B的过程中,B出门了,那么,我们称这个操作失败了,要进行回滚。回滚就是回到事务开始之前的状态,
A还是5块石头,B还是4块石头。
我们把这种要么一起成功(A帐户成功减少一块石头,同时B得到一块石头),要么一起失败(A回到原来状态,B也回到原来状态)的操作叫原子性操作。
如果把一个事务可看作是一个程序,它要么完整的被执行,要么完全不执行。这种特性就叫原子性。
redis事务的本质:一组命令的集合!! 一个事务的命令会被序列化,在执行事务的时候会按顺序执行,一次性、排他性、顺序性。
redis单条命令是保存原子性的,但事物不保证原子性
redis事务没有隔离级别的概念
一、redis的事物:
- 开启事务
- 命令入队
- 执行事务
127.0.0.1:6379> MULTI 开启事务
OK
127.0.0.1:6379> set a 1 命令入队
QUEUED
127.0.0.1:6379> set b 2
QUEUED
127.0.0.1:6379> set c 3
QUEUED
127.0.0.1:6379> set d 4
QUEUED
127.0.0.1:6379> get a
QUEUED
127.0.0.1:6379> get c
QUEUED
127.0.0.1:6379> EXEC 执行事务
1) OK
2) OK
3) OK
4) OK
5) "1"
6) "3"
127.0.0.1:6379> DISCARD 取消事务(事务队列中的命令都不会被执行)
注意当执行完exec之后一个事务已经被执行完。若再次执行事务需要重新开始创建事务
二、监控
监控!!
悲观锁:无论什么时候都会枷锁,认为什么时候都会出现问题!
乐观锁:无论什么时候都不会枷锁,认为什么时候都不会出现问题!更新数据判断一下再次期间是否有人更改过此数据。
获取version,更新的时候比较version
redis检测测试:
127.0.0.1:6379> set qian 100 设置一共100元
OK
127.0.0.1:6379> set out 0 设置话费0元
OK
127.0.0.1:6379> WATCH qian 监控此key相当于获取值
OK
127.0.0.1:6379> MULTI 开始事务
OK
127.0.0.1:6379> DECRBY qian 20 件20
QUEUED
127.0.0.1:6379> INCRBY out 20 加20
QUEUED
127.0.0.1:6379> EXEC 事务执行完毕
1) (integer) 80
2) (integer) 20
测试多线程修改值,监视失败!!
打开两个终端shell
在第一个shell中
127.0.0.1:6379> WATCH qian 监控相当于获取值
OK
127.0.0.1:6379> MULTI 开始事务
OK
127.0.0.1:6379> DECRBY qian 50 减50
QUEUED
127.0.0.1:6379> INCRBY out 50 加50
QUEUED
先不要执行事务,直接在第二个shell终端中连接redis(也就是重新打开一个线程)
127.0.0.1:6379> set qian 2000 重新更改值为2000
OK
然后再去第一个shell中执行事务。会发现事务执行失败
为什么会失败??
因为监控的时候获取值。之后执行事务的时候会去比较值当发现值不一致时会失败
127.0.0.1:6379> EXEC
(nil)
乐观锁失效如何恢复??
127.0.0.1:6379> UNWATCH 首先解锁后面依次执行
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY qian 20
QUEUED
127.0.0.1:6379> INCRBY out 20
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 1980
2) (integer) 40