Redis事务本质

一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行

Redis事务特点

  • 一次性
  • 顺序性
  • 排他性

==Redis单条命令是保证原子性的,但是事务不保证原子性。==

==Redis事务没有隔离级别的概念==

事务执行命令

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)> exec
1) OK
2) OK
3) "v2"
127.0.0.1:6379> get k2
"v2"

放弃事务命令

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> set k6 v6
QUEUED
127.0.0.1:6379(TX)> DISCARD
OK
127.0.0.1:6379> get k5
(nil)

编译型异常,所有的命令都不会执行

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
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
# 所有命令都未执行
127.0.0.1:6379> keys *
(empty array)

运行时异常,错误的命令抛出异常,其他命令继续执行(没有原子性的表现)

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> incr k1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
#运行时抛出错误异常,其他命令继续执行
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"

乐观锁实现

悲观锁

认为什么时候都会出问题,无论干什么都会加锁

乐观锁
认为什么时候都不会出问题,所以不会上锁。更新数据的时候去判断一下,在此期间是否有人更改了数据。

  1. 获取version
  2. 更新的时候比较version

正常加锁执行

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
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20

加锁后,数据被篡改

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 10
QUEUED
127.0.0.1:6379(TX)> incrby money 10
QUEUED

#另一线程此时修改了数据
127.0.0.1:6379(TX)> exec
(nil)
# 另一线程
127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379> get money 
"1000"