Redis入门 事务(乐观锁)

Redis基础

事务

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

一次性、顺序性、排他性的执行命令!

Redis的事务中没有隔离级别的概念,也就不可能发生脏读、幻读!
所有的命令在事务中,并没有直接被执行,而是在发起执行命令的时候,才会一起执行!

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

Redis的事务:三步!

  • 开启事务:multi
  • 命令入队:普通的命令
  • 执行事务:exec

正常执行事务

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> get k1
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec   #执行事务
1) OK
2) OK
3) "v1"
4) OK

放弃事务

127.0.0.1:6379> flushdb
OK
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> set k4 v4
QUEUED
127.0.0.1:6379> discard   #放弃事务  
OK
127.0.0.1:6379> get k4    #队列都不会被执行
(nil)

编译型异常(Java中是代码错误,Redis中就是命令错误),事务中的一切命令都不会被执行

127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> sets k2 v2   #错误的命令
(error) ERR unknown command `sets`, with args beginning with: `k2`, `v2`, 
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec   #执行事务报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k3   #所有的命令都不会执行
(nil)

运行时异常(就是语法错误,比如1/0),执行事务的时候,其他命令可以正常执行!错误命令抛出异常

127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 k2
QUEUED
127.0.0.1:6379> incr k1   #语法错误,不能对字符串进行自增
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range  #报出语法错误
3) OK
4) "v2"
127.0.0.1:6379> get k2   #其他命令正常执行!
"v2"
127.0.0.1:6379> get k1
"k2"

乐观锁

顾名思义:就很乐观,认为什么时候都不会出错,所以不会上锁!

没加锁,那么万一有人改动数据怎么办呢?更新的时候去判断一下,在此期间有没有人去修改这个数据就好了!

Redis监视测试!watch

  • 正常执行成功
127.0.0.1:6379> set money 100    #你银行卡里有100块钱
OK
127.0.0.1:6379> set out 0    #支出为0
OK
127.0.0.1:6379> watch money    #监视你的银行卡
OK
127.0.0.1:6379> multi   #开启事务
OK
127.0.0.1:6379> decrby money 30   #花了三十买了点吃的
QUEUED
127.0.0.1:6379> incrby out 30   #这时候支出30,记着帐回家报销
QUEUED
127.0.0.1:6379> exec  #执行事务
1) (integer) 70
2) (integer) 30
  • 多线程修改值,执行失败
#第一个线程,就是你自己
127.0.0.1:6379> watch money    #监视银行卡
OK
127.0.0.1:6379> multi    #开启事务
OK
127.0.0.1:6379> decrby money 20   #准备再花20块钱给你媳妇买朵花
QUEUED
127.0.0.1:6379> incrby out 20    #马上又得支出20
QUEUED


#这时候你还没有执行事务,你媳妇(第二个线程)发善心了,给你零花钱打进去了100块钱,你还不知道这事,但是被监视到了银行卡余额变化了!
127.0.0.1:6379> get money  #一看你已经剩70块钱了
"70"
127.0.0.1:6379> incrby money 100   #马上给你又发了100块零花钱
(integer) 170


#这时候你再执行事务,就会失败 (第一个线程)
127.0.0.1:6379> exec   #执行失败
(nil)

那么怎么解决这个问题呢,你还急着想买东西呢!发现钱用不了就很僵硬

#很简单,你先 去掉监视,然后重新监视最新数据就好啦,相当于刷新一下得到最新数据,再次监视
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 20 #花二十
QUEUED
127.0.0.1:6379> incrby out 20 #支出加二十
QUEUED
127.0.0.1:6379> exec  #执行事务,比对监视的值有没有发生变化,如果变化了就失败,反之则成功!
1) (integer) 150
2) (integer) 50

乐观锁可以用于秒杀场景!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值