跳到主要内容

Redis 事务基础

Redis事务是一种将多个命令打包执行的机制,确保这些命令按顺序执行,且在执行过程中不会被其他客户端的命令打断。事务的核心目标是保证一组命令的原子性,即要么全部执行成功,要么全部不执行。

什么是Redis事务?

Redis事务通过 MULTIEXECDISCARDWATCH 四个命令来实现。事务的执行过程分为三个阶段:

  1. 开启事务:使用 MULTI 命令开启一个事务。
  2. 命令入队:在事务开启后,所有后续命令会被放入一个队列中,而不是立即执行。
  3. 执行事务:使用 EXEC 命令执行队列中的所有命令。
备注

Redis事务并不支持回滚(rollback)。如果在事务执行过程中某个命令失败,其他命令仍会继续执行。

基本命令

1. MULTI

MULTI 命令用于开启一个事务。执行该命令后,Redis会将后续的所有命令放入队列中,直到 EXECDISCARD 被调用。

bash
127.0.0.1:6379> MULTI
OK

2. EXEC

EXEC 命令用于执行事务队列中的所有命令。执行后,Redis会返回每个命令的执行结果。

bash
127.0.0.1:6379> SET key1 "Hello"
QUEUED
127.0.0.1:6379> SET key2 "World"
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK

3. DISCARD

DISCARD 命令用于取消事务,清空事务队列中的所有命令。

bash
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key1 "Hello"
QUEUED
127.0.0.1:6379> DISCARD
OK

4. WATCH

WATCH 命令用于监视一个或多个键。如果在事务执行之前,这些键的值被其他客户端修改,则事务将不会执行。

bash
127.0.0.1:6379> WATCH key1
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key1 "New Value"
QUEUED
127.0.0.1:6379> EXEC
(nil) # 如果 key1 被其他客户端修改,事务将不会执行

事务的原子性

Redis事务的原子性体现在:事务中的所有命令要么全部执行成功,要么全部不执行。然而,Redis事务并不支持回滚机制。如果某个命令执行失败,其他命令仍会继续执行。

警告

Redis事务的原子性仅限于命令的执行顺序,而不包括命令的执行结果。如果某个命令执行失败,Redis不会自动回滚已执行的命令。

实际应用场景

场景1:库存扣减

假设我们有一个电商系统,需要在用户下单时扣减库存。我们可以使用Redis事务来确保库存扣减的原子性。

bash
127.0.0.1:6379> WATCH stock
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY stock 1
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 99 # 假设库存初始为100

场景2:用户积分更新

在用户完成某个操作后,我们需要同时更新用户的积分和操作记录。使用Redis事务可以确保这两个操作同时成功或失败。

bash
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCRBY user:1000:points 10
QUEUED
127.0.0.1:6379> LPUSH user:1000:actions "completed_task"
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 110 # 假设用户原有100积分
2) (integer) 1 # 操作记录列表的长度

总结

Redis事务提供了一种将多个命令打包执行的机制,确保这些命令按顺序执行且在执行过程中不会被其他客户端的命令打断。虽然Redis事务不支持回滚,但在许多场景下,它仍然是一个非常有用的工具。

提示

如果你需要更复杂的逻辑控制,可以考虑使用Redis脚本(Lua脚本),它提供了更强大的编程能力。

附加资源

练习

  1. 使用Redis事务实现一个简单的转账功能,确保转账过程中余额的原子性更新。
  2. 尝试使用 WATCH 命令实现一个乐观锁机制,防止并发修改。