Redis 的事务提供了一种将多个命令打包成一个单独的单元来执行的方式,确保这些命令要么全部成功执行,要么在出现错误时都不执行。Redis 通过 MULTI
、EXEC
、DISCARD
和 WATCH
命令来支持事务。
事务的工作流程
- 开始事务:客户端发送
MULTI
命令给 Redis 服务器,表示接下来的所有命令都是事务的一部分。 - 命令入队:从
MULTI
开始直到EXEC
被调用之前,客户端可以向服务器发送任意数量的命令,但这些命令不会立即被执行;相反,它们会被放入一个队列中等待。 - 执行事务:当客户端发送
EXEC
命令时,Redis 会按照顺序逐个执行队列中的所有命令,并在最后将结果一次性返回给客户端。 - 取消事务:如果客户端决定不执行事务,可以发送
DISCARD
命令,这将清空事务队列并放弃事务。 - 乐观锁(可选):使用
WATCH
命令可以让 Redis 监视一个或多个键。如果在EXEC
执行前任何被监视的键被其他客户端修改了,那么整个事务都会失败,并且不会执行事务中的任何命令。这种方式提供了简单的乐观锁机制。
事务的特点
- 原子性:在一个事务中,所有的命令都被视为一个整体。要么所有命令都成功执行,要么由于某些原因(如语法错误)导致没有任何命令被执行。
- 隔离性:虽然 Redis 是单线程处理命令,但在事务执行期间,它仍然会接收来自其他客户端的命令。因此,事务并不提供真正的数据库事务中的隔离级别。不过,通过
WATCH
可以实现一定程度的并发控制。 - 一致性:Redis 不支持回滚操作。一旦事务开始执行,即使中途出现错误(如命令语法错误),已经执行的命令也不会被撤销。
- 持久性:如果 Redis 配置了 AOF 或 RDB 持久化,那么事务的结果也会被持久化到磁盘上。
示例
> MULTI
OK
> SET key1 value1
QUEUED
> GET key1
QUEUED
> INCR counter
QUEUED
> EXEC
1) OK
2) "value1"
3) (integer) 1
在这个例子中,SET
、GET
和 INCR
命令被添加到了事务队列中。当 EXEC
发送后,Redis 执行了这些命令并将结果一起返回。
注意事项
- 如果事务中的某个命令有语法错误,Redis 会在
EXEC
时返回错误信息,但已经执行的命令不会被回滚。 WATCH
机制用于检测事务执行前数据是否发生变化,如果变化则整个事务不会执行。这对于需要一定一致性的应用场景非常有用。- 事务不是用来解决高并发写冲突的最佳方案,因为 Redis 不支持真正的回滚和复杂的锁定机制。对于更复杂的情况,可能需要考虑其他方法,比如 Lua 脚本。