Redis 事务处理

本文详细介绍了Redis事务的使用方法,包括`MULTI`开启事务,`EXEC`执行事务,`DISCARD`丢弃事务,以及`WATCH`监视键的操作。通过实例展示了事务中可能出现的语法错误和类型错误,以及Redis如何处理这些错误。重点讲解了乐观锁机制的应用和事务在避免竞态条件中的作用。
摘要由CSDN通过智能技术生成

本文参考于 Redis 中文文档

相关命令

  • MULTI:multiple,多个,这里用来开启事务,总是返回 OK,之后的命令不会立即执行,而是进入一个命令队列。
  • EXEC:execute,执行,这里用来执行队列中的事务。
  • DISCARD:丢弃,这里用来丢弃队列中的所有事务。
  • WATCH:这里用来监视某些键, 如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消。CAS(check and set)操作。

实现

准备三个键值对

2021 年 21 岁 体重 140

127.0.0.1:6379> set year 2021
OK
127.0.0.1:6379> set age 21
OK
127.0.0.1:6379> set weight 140
OK

开启事务

## 开启事务
127.0.0.1:6379> MULTI
OK
## 过一年
127.0.0.1:6379> INCR year
QUEUED
## 长一岁
127.0.0.1:6379> INCR age
QUEUED
## 长两斤
127.0.0.1:6379> INCRBY weight 2
QUEUED
## 执行事务
127.0.0.1:6379> EXEC
## 执行结果
1) (integer) 2022
2) (integer) 22
3) (integer) 142

可能出现的错误

可能出现两种错误

  • 在执行 EXEC 之前,入队的命令出现语法错误
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCR year
QUEUED
127.0.0.1:6379> INCR age
QUEUED
## 没有使用INCRBY 使用了INCR 不可以带参数
127.0.0.1:6379> INCR weight 2
## 翻译:INCR 命令的参数数量错误
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379> EXEC
## 翻译:执行终止,由于先前的错误,事务被丢弃
(error) EXECABORT Transaction discarded because of previous errors.

结果

127.0.0.1:6379> get year
"2022"
127.0.0.1:6379> get age
"22"
127.0.0.1:6379> get weight
"142"

可以看到结果,事务中途命令有错误,整个事务被丢弃,并没有改变原来的键值对

  • 没有发生语法错误,在执行过程中失败,例如,用列表的命令处理了字符串的键
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCR year
QUEUED
127.0.0.1:6379> INCR age
QUEUED
## LLEN 返回列表的长度
127.0.0.1:6379> LLEN weight
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 2023
2) (integer) 23
## 翻译:类型错误,针对的键持有错误的值
3) (error) WRONGTYPE Operation against a key holding the wrong kind of value

结果

127.0.0.1:6379> get year
"2023"
127.0.0.1:6379> get age
"23"
127.0.0.1:6379> get weight
"142"

可以发现前两个键值对发生了改变,但是第三个因为类型错误没有改变成功。

但是 Redis 并没有回滚当前事务。

Redis 中文官方文档 认为这样做是没啥问题的:

  • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
  • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

翻译一下:

  • 开发人员的锅凭什么要我背呢
  • 我就是快

乐观锁机制

val = get year
val = val +1
set year val

在编程环境下执行上述逻辑时,单个客户端执行并没有什么问题,倘若两个客户端先后执行了第一句,同时拿到 year 的当前数据 2023。执行后两句的时候都会设置为 2024,但是原有的逻辑下,正确的应该是 2025。

可以使用 WATCH 命令来监视 year 键

WATCH year
MULTI
val = get year
val = val +1
set year val
EXEC

当前逻辑下,在 WATCH 执行之后, EXEC 执行之前,如果 year 的值发生了变化,当前事务就会失败。

在 EXEC 执行之后,自动取消对键的监视,也可以使用 UNWATCH 来手动取消

也可以使用 lua 脚本的原子性来实现事务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值