Redis 事务是一种将多个命令打包在一起执行的机制。通过使用事务,可以确保一系列命令在一次执行中依次执行,而不会被其他客户端的命令请求打断。
Redis 事务的执行分为以下几个步骤:
Redis 事务的一个重要特性是乐观锁。在执行事务期间,Redis 不会对数据进行锁定或阻塞其他客户端操作,而是在执行事务时记录了事务执行期间所依赖的键的状态,如果在执行 EXEC 命令之前检测到这些键的状态发生了变化,那么事务将会被中断并放弃执行。
需要注意的是,Redis 的事务是原子性的,要么全部执行成功,要么全部放弃执行。如果在事务执行期间出现错误,事务中的所有命令都不会被执行,并且不会对数据产生任何影响。Redis 事务的应用场景包括批量操作、原子操作、队列操作等,通过将多个命令打包在一起执行,可以减少网络通信开销,提高性能,并保持一致性。
悲观锁 :
乐观锁 :
在实际应用中,选择使用悲观锁还是乐观锁取决于具体的需求和场景。悲观锁可以确保数据的一致性,但可能带来较高的开销和性能影响。乐观锁则通过乐观的假设减少了锁的竞争,提高了并发性能,但需要在冲突发生时进行额外的处理。
出现语法错误时,EXEC 后会直接返回错误,语法正确的命令也不会执行
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> SET name cx
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
出现运行错误时,比如使用集合的命令操作字符串,这种错误在执行之前无法被发现,所以这种情况下正确的命令会被执行。Redis 的事务机制并不支持事务回滚(rollback)操作,因此当出现事务运行错误需要自己收拾烂摊子。
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET name caixing
QUEUED
127.0.0.1:6379> SADD name cx
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
WATCH 命令用于实现乐观锁机制,它可以在事务执行之前监视一个或多个键。WATCH 命令会监视指定的键,如果在执行事务期间有其他客户端修改了被监视的键,那么当前事务将被打断,不会执行,可以通过检查执行 EXEC 命令的返回值来判断是否执行了事务。
使用 WATCH 命令监视一个或多个键:
WATCH key1 key2 ...
可以指定一个或多个键来监视。一旦执行了 WATCH 命令,Redis 会将这些键标记为被监视状态。
比如说如果要自己利用 GET 和 SET 实现 INCR 函数,伪代码如下所示。这段代码可能出现竞态条件,key 的原始值为 6,期望情况应该是将 key 变为 8,但是如果两个客户端同时(在对方尚未返回时)开始执行这段代码,那么最后 key 是 7。
$val = GET $key
if $val is null
$val = 0
$val = $val + 1
SET $key $val
虽然事务提供了原子性,但是由于事务每条命令的执行结果是同时返回的,所以不适用这种前后具有依赖关系的命令,为了解决这个问题,可以使用 WATCH 来实现 GET 获得键值后不允许其他客户端修改键以防止竞态条件。
在执行事务前使用 WATCH 监视 key,在执行事务前 key 发生了改变,变成了 3,因此事务未执行。WATCH 的监控一直持续到 EXEC 命令。
127.0.0.1:6379> SET key 1
OK
127.0.0.1:6379> WATCH key
OK
127.0.0.1:6379> SET key 2
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key 3
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> GET key
"2"
修改刚刚的伪代码如下。
WATCH $key
$val = GET $key
if $val is null
$val = 0
$val = $val + 1
MULTI
SET $key $val
EXEC