Redis基本事务操作

suaxi
2021-01-02 / 0 评论 / 60 阅读 / 正在检测是否收录...

关系型数据库:ACID原则

非关系型数据库:Redis事务是一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行的过程中顺序执行(一次性、顺序性、排他性)

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

事务中所有的命令并没有被直接执行,只有发起执行命令(Exec)时才会执行


redis的事务:

  • 开启事务(multi)
  • 命令入队
  • 执行事务(exec)
正常执行事务
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379> set key01 hello #命令入队
QUEUED
127.0.0.1:6379> set key02 nihao
QUEUED
127.0.0.1:6379> get key01
QUEUED
127.0.0.1:6379> set key03 xiexie
QUEUED
127.0.0.1:6379> EXEC #执行事务
1) OK
2) OK
3) "hello"
4) OK
127.0.0.1:6379> 
取消事务
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379> set key01 hello
QUEUED
127.0.0.1:6379> set key02 nihao
QUEUED
127.0.0.1:6379> set key03 xiexie
QUEUED
127.0.0.1:6379> DISCARD #取消事务
OK
127.0.0.1:6379> get key03 #事务队列中的命令都不会被执行,此处查询结果为空
(nil)
127.0.0.1:6379> 
编译型异常(代码中存在错误),事务中的所有命令都不会被执行
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> 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> EXEC #执行事务报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1 #事务队列中的所有命令都没有被执行
(nil)
127.0.0.1:6379> 
运行时异常(1/0问题),事务队列中除有问题的语句外其他的都会被执行(无原子性)
127.0.0.1:6379> set k1 hello
OK
127.0.0.1:6379> MULTI
OK
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) (error) ERR value is not an integer or out of range #自增语句执行失败,其后的语句执行成功
2) OK
3) OK
4) "v3"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"
127.0.0.1:6379> 

Watch监控

悲观锁:认为什么时候都会出现问题,无论做什么都会加锁

乐观锁:认为什么时候都不会出现问题,不会上锁,在更新数据的时候会去判断在此期间是否有人修改过数据

  • 获取version
  • 更新的时候比较version

Redis监视测试:

# 正常执行
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> 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
127.0.0.1:6379> 

乐观锁:(常用于电商秒杀系统)

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 #在执行之前有其他的线程修改了money,会导致这里的事务执行失败
(nil)
127.0.0.1:6379> 
127.0.0.1:6379> UNWATCH #如果发现事务执行失败,就先解锁
OK
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 money 5
QUEUED
127.0.0.1:6379> exec #对比监控的信息是否发生了变化,如果没有,则执行成功,否则执行失败
1) (integer) 0
2) (integer) 5
127.0.0.1:6379> 
0

评论 (0)

取消