【Redis】深入理解 Redis 事务:命令、应用与实战案例

发布于:2025-06-24 ⋅ 阅读:(20) ⋅ 点赞:(0)

一、Redis 事务

1. 什么是事务

Redis 的事务和 Mysql 的事务概念类似,即把一系列操作绑定成组,让这组操作能够批量执行。

区别主要体现在以下几个方面:

  • 弱化的原子性:Redis 不支持回滚机制,只能批量执行命令,无法做到 “一个失败就恢复到初始状态”。也就是说,如果事务中的某个命令失败,Redis 无法自动撤销之前的操作。

  • 不保证一致性:Redis 事务没有约束条件和回滚机制,因此不能确保事务前后数据的一致性。MySQL 的一致性保证的是在事务执行前后,结果是有效且合理的,避免出现非法状态。

  • 不需要隔离性:Redis 不支持事务隔离级别,因为它是单线程处理请求的,不会出现并发事务执行的情况。

  • 不需要持久性:Redis 数据是保存在内存中的,是否开启持久化与事务无关,完全由 redis-server 配置决定。

Redis 事务本质上是通过维护一个 事务队列 实现的。客户端每次在事务中执行操作时,会将命令发送到服务器并加入事务队列,但命令不会立即执行。只有在收到 EXEC 命令时,所有操作才会按顺序执行。

因此,Redis 的事务功能相比 MySQL 要弱得多,只能保证事务中的操作按顺序执行,不会被其他客户端的命令插队。

2. 事务命令

在这里插入图片描述

Redis 的事务命令具体如下:

命令 功能描述
MULTI 标记事务开始
EXEC 执行事务中的所有命令
DISCARD 取消事务,放弃所有命令
WATCH 监视键,实现乐观锁
UNWATCH 取消所有 WATCH 的键监视

下面具体介绍每个命令的作用与实例:

1. MULTI - 开启事务

功能:标记事务块的开始
语法MULTI
特点:后续命令将进入队列,直到执行EXEC
实例

redis> MULTI
OK
redis> SET user:100 "Alice"
QUEUED
redis> INCR counter
QUEUED

2. EXEC - 执行事务

功能:执行所有事务块内的命令
语法EXEC
返回值:按顺序返回各命令的执行结果
实例(接上例):

redis> EXEC
1) OK          # SET命令结果
2) (integer) 3 # INCR命令结果

3. DISCARD - 取消事务

功能:放弃所有已入队的命令
语法DISCARD
实例

redis> MULTI
OK
redis> SET temp "value"
QUEUED
redis> DISCARD
OK
redis> GET temp  # 命令未执行
(nil)

4. WATCH - 监视键

功能:监视键的CAS操作(Check-And-Set)
语法WATCH key [key ...]
特点:如果被监视键在EXEC前被修改,则事务失败
实例

# 终端1
redis> WATCH account:100
OK
redis> MULTI
OK
redis> GET account:100
QUEUED

# 终端2(同时操作)
redis> SET account:100 "modified"

# 终端1继续
redis> EXEC  # 返回nil表示执行失败
(nil)

5. UNWATCH - 取消监视

功能:取消所有WATCH的键监视
语法UNWATCH
实例

redis> WATCH key1 key2
OK
redis> UNWATCH
OK

3. 实例场景演示

案例1:银行转账(使用WATCH实现乐观锁)

# 初始化数据
redis> SET account:A 1000
OK
redis> SET account:B 500
OK

# 转账事务
redis> WATCH account:A account:B  # 监视账户
OK
redis> MULTI
OK
redis> DECRBY account:A 200       # A账户减200
QUEUED
redis> INCRBY account:B 200       # B账户加200
QUEUED
redis> EXEC
1) (integer) 800  # account:A新值
2) (integer) 700  # account:B新值

案例2:库存扣减(处理执行错误)

redis> SET inventory "10"
OK
redis> MULTI
OK
redis> DECR inventory      # 正常命令
QUEUED
redis> INCRBY inventory "abc"  # 错误命令(非数字)
QUEUED
redis> GET inventory       # 正常命令
QUEUED
redis> EXEC
1) (integer) 9            # DECR执行成功
2) (error) ERR value is not an integer or out of range
3) "9"                    # GET执行成功

案例3:商品抢购(事务+过期时间)

# 商品初始库存100,有效期10秒
redis> SET item:123:stock 100 EX 10
OK

redis> WATCH item:123:stock
OK
redis> MULTI
OK
redis> DECR item:123:stock
QUEUED
redis> EXEC  # 返回剩余库存
(integer) 99

网站公告

今日签到

点亮在社区的每一天
去签到