事务
前言
一、exec
1.1 认识
exec
命令用于执行在事务中排队的所有命令。在执行 multi
命令之后,所有后续的命令都会被排队等待执行,直到调用 exec
时才会真正执行这些命令。exec
会返回一个数组,其中每个元素对应事务中每个命令的执行结果。
事务工作流:
-
客户端首先通过
multi
命令进入事务模式。 -
客户端执行一个或多个
Redis
命令,这些命令不会立即执行,而是被排队等待执行。 -
当调用
exec
时,所有排队的命令会被执行,结果返回给客户端。
事务的执行, 事务中的所有命令要么成功执行,要么都不执行,这取决于事务是否成功。每个命令的执行结果会作为一个数组项返回,[error, result]
。如果执行成功,error
为 null
,result
为命令的结果;如果有错误,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 认识
multi
是 Redis
客户端用于启动事务操作的命令。它用于将多个命令封装在一起,使它们作为一个原子操作来执行。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">