跳到主要内容

事务

2025年01月10日
柏拉文
越努力,越幸运

前言


Redis 文档

一、exec


1.1 认识

exec 命令用于执行在事务中排队的所有命令。在执行 multi 命令之后,所有后续的命令都会被排队等待执行,直到调用 exec 时才会真正执行这些命令。exec 会返回一个数组,其中每个元素对应事务中每个命令的执行结果。

事务工作流:

  1. 客户端首先通过 multi 命令进入事务模式。

  2. 客户端执行一个或多个 Redis 命令,这些命令不会立即执行,而是被排队等待执行。

  3. 当调用 exec 时,所有排队的命令会被执行,结果返回给客户端。

事务的执行, 事务中的所有命令要么成功执行,要么都不执行,这取决于事务是否成功。每个命令的执行结果会作为一个数组项返回,[error, result]。如果执行成功,errornullresult 为命令的结果;如果有错误,error 将包含错误信息,result 会是 null

1.2 语法

exec(callback?: Callback<[error: Error, result: unknown][]>): Promise<[error: Error, result: unknown][]>

1.3 用法

redis.multi()
.set('key1', 'value1')
.set('key2', 'value2')
.exec((err, results) => {
if (err) {
console.error('Transaction failed:', err);
} else {
console.log('Transaction results:', results);
}
});

二、multi


2.1 认识

multiRedis 客户端用于启动事务操作的命令。它用于将多个命令封装在一起,使它们作为一个原子操作来执行。Redis 的事务机制使得所有在 multi() 中排队的命令能够一并执行,要么全部成功,要么全部失败。

multi 工作原理:

  • 事务模式:当不使用管道时,multi() 会启动一个 Redis 事务,所有命令会被排队执行,直到你调用 exec() 来执行它们。在事务执行时,Redis 会确保这些命令作为原子操作一并执行,若其中一个命令失败,其他命令也不会执行。

  • 管道模式:当启用管道时,multi() 会将所有命令批量发送到 Redis,但不会立即执行,这可以提高多命令执行的效率,但不保证原子性。执行时,命令会被并行处理。

2.2 语法

multi(options: { pipeline: false }): Promise<"OK">
multi(): ChainableCommander
multi(options: { pipeline: true }): ChainableCommander
multi(commands?: unknown[][]): ChainableCommander
  • options: { pipeline: false }: 启用事务模式并禁用管道模式(即每个命令都是按顺序执行的,确保事务的原子性)。返回值为 OK,表示事务模式成功启动。

  • multi(): 启动一个新的事务并返回一个可链式调用的对象 ChainableCommander,它可以继续添加更多的 Redis 命令(例如 set, get 等),这些命令会被排队等待执行。

  • options: { pipeline: true }: 启用管道模式(pipeline),这样 Redis 命令不会立即执行,而是将所有命令批量发送到 Redis 服务器。这可以用来提高性能,但不会保证事务的原子性。返回一个 ChainableCommander 对象,表示管道模式下的命令队列。

  • multi(commands?: unknown[][]): 直接传入一个包含多个命令和参数的数组(如 [["set", "key1", "value1"], ["get", "key1"]]),启动一个事务并将这些命令排队。返回一个 ChainableCommander 对象。

2.3 用法

事务模式: 命令被排队执行,直到 exec 被调用,所有命令会按顺序执行。

redis.multi()
.set('key1', 'value1')
.set('key2', 'value2')
.get('key1')
.exec((err, results) => {
console.log(results); // 事务执行的结果
});

管道模式: 在管道模式下,所有命令会被批量发送到 Redis,执行时会并行处理,效率更高,但无法保证原子性。

redis.multi({ pipeline: true })
.set('key1', 'value1')
.set('key2', 'value2')
.get('key1')
.exec((err, results) => {
console.log(results); // 管道模式下的结果
});

三、discard


3.1 认识

discard()Redis 事务操作中的一个命令,用于取消当前事务中的所有命令,并放弃所有已经排队的命令。它可以在事务开始后,决定不执行之前排队的命令时使用。

3.2 语法

discard(callback?: Callback<"OK">): Promise<"OK">