Redis基础—五、Redis事务、乐观锁

Redis基础—5、Redis事务、乐观锁

一、redis事务简介

1、简介

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。

我们可以理解Redis事物为一个脚本,脚本中如果出现编译时错误(代码有错),整条脚本都不会被执行,并且并抛弃。脚本中如果出现运行时错误(1/0等逻辑错误),除了该条指令其他的语句依然会被执行。

2、相关命令

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 k3 v3
QUEUED
127.0.0.1:6379> exec                      #执行事务
1) OK
2) OK
3) OK
127.0.0.1:6379> get k1                    #可以拿到
"v1"
127.0.0.1:6379> get k3
"v3"
127.0.0.1:6379> multi                     #开启事务
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> discard                   #放弃事务
OK
127.0.0.1:6379> get k4                   #拿不到k4
(nil)
127.0.0.1:6379> multi                     #开启事务
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> se k5 v5
(error) ERR unknown command `se`, with args beginning with: `k5`, `v5`,        #语法错误
127.0.0.1:6379> set k6 v6
QUEUED
127.0.0.1:6379> exec                    #执行
(error) EXECABORT Transaction discarded because of previous errors.    #所有事务都不会执行
127.0.0.1:6379> get k6                  #拿不到
(nil)
127.0.0.1:6379> multi                   #开启事务
OK 
127.0.0.1:6379> set k7 v7               
QUEUED
127.0.0.1:6379> incr k7                 #对字符串进行增加一操作(逻辑错误)
QUEUED
127.0.0.1:6379> set k8 v8
QUEUED
127.0.0.1:6379> exec                    #其他的会被执行
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379> get k8
"v8"

二、Redis实现乐观锁

悲观锁:

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

乐观锁:

  • 很乐观,认为什么时候都不会出现问题,所以不会加锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据
  • 获取version
  • 更新的时候比较version

我们在redis中可以通过watch来实现对一个对象的乐观锁,通过watch来获取一个属性的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> decrby money
(error) ERR wrong number of arguments for 'decrby' command
127.0.0.1:6379> discard
OK
127.0.0.1:6379> watch money                        #监控money的值
OK
127.0.0.1:6379> multi                              #开启事务
OK
127.0.0.1:6379> decrby money 30                    #减少余额30
QUEUED
127.0.0.1:6379> incrby out 20                      #增加支出20
QUEUED 
127.0.0.1:6379> exec                               #执行
1) (integer) 70
2) (integer) 20
127.0.0.1:6379> watch money                        #先查看下money
OK
127.0.0.1:6379> multi                              #开启一下
OK
127.0.0.1:6379> incrby money 50                     
QUEUED

这时我们不提交事务,我们模拟一下另外一个线程对money进行改变的场景,这里第二个线程将这个钱数减少了20

127.0.0.1:6379> get money
"70"
127.0.0.1:6379> decrby money 50
(integer) 20

再执行下第一个线程的事务

127.0.0.1:6379> get money
QUEUED
127.0.0.1:6379> exec
(nil)

这里执行出现nil,这就代表着乐观锁生效了,事务没有执行成功。

那假如我们在第二个线程也对money做了一些改变,但是最终值与原来第一个线程watch时的值相同呢?

第一个线程,

127.0.0.1:6379> set jj 80
OK
127.0.0.1:6379> watch jj          #加锁
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby jj 30      #这里第二个线程先对他增加50,再减少50
QUEUED
127.0.0.1:6379> exec             #执行
(nil)

发现不大行,redis的事务处理与其值没有很大的关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值