Redis系列(四)-Redis事务与监控(Redis的事务和使用监控实现乐观锁与悲观锁)

简介

Redis单条命令是保证原子性的,但是Redis事务是不保证原子性的(原子性:要么都成功,要么都失败)

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

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

具有一次性、顺序性、排他性,就好像按照队列在执行

------队列 set set set 执行------

所有的命令在事务中,并没有直接被执行!只有发起执行的命令后才会执行。exec命令。

redis的事务步骤:

1、开启事务:multi

2、命令入队:自动入队

3、执行事务:exec

开启事务
127.0.0.1:6379> MULTI			# 开启redis事务
OK
命令入队
127.0.0.1:6379> MULTI			# 开启redis事务
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)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> get k3
QUEUED
执行事务
127.0.0.1:6379(TX)> exec		# 执行事务
1) OK
2) OK
3) "v2"
4) OK
5) "v3"
127.0.0.1:6379> 
放弃事务
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)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> DISCARD		# 放弃事务
OK
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> 
编译型异常(代码问题)

代码出现出错,命令有问题,事务中所有的命令都不会执行。

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 v3
QUEUED
127.0.0.1:6379(TX)> getset k3		# 制作一个编译型异常
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> exec			# 执行抛异常
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k5				# set k5 v5 设置失败了
(nil)
127.0.0.1:6379> get k1				# set k1 v1 设置失败了
(nil)
127.0.0.1:6379> 
运行时异常

如果对列中存在语法性错误(1/0),执行的时候其他命令可以正常执行,错误命令会抛出异常

127.0.0.1:6379> set k1 v1		# 设置字符串k1
OK
127.0.0.1:6379> MULTI			# 开启事务
OK
127.0.0.1:6379(TX)> INCR k1		# k1自增加1-这里运行时会报错,字符串不能加1
QUEUED
127.0.0.1:6379(TX)> set k2 v2	# 设置k2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec		# 执行
1) (error) ERR value is not an integer or out of range	# INCR k1报错了,但是依旧正常执行后面语句成功了
2) OK
3) OK
127.0.0.1:6379> get k2			# k2正确执行了
"v2"
127.0.0.1:6379> get k3			# k3正确执行了
"v3"
127.0.0.1:6379> 
Redis监控(乐观锁、悲观锁)

面试经常问的!!!

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

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

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

Redis的监视测试

正常执行成功

127.0.0.1:6379> set money 100		# 账户金额100
OK
127.0.0.1:6379> set out 0			# 使用金额20
OK
127.0.0.1:6379> WATCH money			# 监视money
OK
127.0.0.1:6379> MULTI				# 开启事务
OK
127.0.0.1:6379(TX)> DECRBY money 20	# 账户金额减少20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20	# 使用金额加20
QUEUED
127.0.0.1:6379(TX)>  exec			# 执行事务
1) (integer) 80
2) (integer) 20

多线程执行

我们在刚才的基础上多开一个Xshell客户端2,并打开客户端连接到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			# 开启监控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

我们在不执行第一个客户端的exec命令下,在第二个客户端修改money的值

127.0.0.1:6379> get money
"100"
127.0.0.1:6379> set money 200	# 修改money
OK
127.0.0.1:6379> 

最后在回到客户端1执行exec提交事务

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	# 执行事务失败
(nil)
127.0.0.1:6379> UNWATCH		# 放弃监视
OK
127.0.0.1:6379> WATCH money	# 重新监视,就可以获取最新的值了
......

我们发现客户端1的事务执行失败了。这样我们就成功的给money加上了锁。所以我们可以使用watch当作乐观锁操作!

当我们监视后事务执行失败了,我们需要放弃监视

尾言

本文为狂神说Redis学习笔记
学习地址:https://www.bilibili.com/video/BV1S54y1R7SB?p=21

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值