Redis 事务介绍
Redis 支持事务,但只支持事务中 (A-> 原子性 C-> 一致性 I-> 隔离性 D-> 持久性) A 和 I,使用 Redis 事务要注意以下两点:
1. 在一个 Redis 事务中,Redis 要么执行其中的所有命令,要么什么都不执行。因此,Redis 事务能够保证原子性。
2.Redis 会将一个事务中的所有命令序列化,然后按顺序执行。Redis 不可能在一个 Redis 事务的执行过程中插入执行另一个客户端发出的请求。这样便能保证 Redis 将这些命令作为一个单独的隔离操作执行。
我们正常的观念认为,当执行某一个事务中,有报错就会回滚数据,Redis 并不是这样处理的。 首先明确阐述 Redis 是没有回滚的。然后我们探讨一直性的问题,Redis 一直性的处理方式是,如果语法上明确的出现 ERROR,会认为整个事务就是 ERROR,但数据上出现 ERROR,其余命令还是会成功。 以下是语法出错,这个事务也就是错误的,可无休止的键入命令,但都不会成功。
以下是,数据错误,有重复的 key 出现,但并不影响其余命令的操作。
# redis 事务网络中断或者服务停止宕机的修复方式
当某个客户端正在执行一次事务时,如果它在调用 MULTI 命令之前就从 Redis 服务端断开连接,那么就不会执行事务中的任何操作;相反,如果它在调用 EXEC 命令之后才从 Redis 服务端断开连接,那么就会执行事务中的所有操作。当 Redis 使用只增文件(AOF:Append-only File)时,Redis 能够确保使用一个单独的 write (2) 系统调用,这样便能将事务写入磁盘。
如果 Redis 服务器宕机,或者系统管理员以某种方式停止 Redis 服务进程的运行,那么 Redis 很有可能只执行了事务中的一部分操作。Redis 将会在重新启动时检查上述状态,然后退出运行,并且输出报错信息。
使用 redis-check-aof 工具可以修复上述的只增文件,这个工具将会从上述文件中删除执行不完全的事务,这样 Redis 服务器才能再次启动。
# redis 事务相关命令
MULTI -> 用于标记事务块的开始。Redis 会将后续的命令逐个放入队列中,然后才能使用 EXEC 命令原子化地执行这个命令序列。这个命令的返回值是一个简单的字符串,总是 OK。
EXEC -> 在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态。当使用 WATCH 命令时,只有当受监控的键没有被修改时,EXEC 命令才会执行事务中的命令,这种方式利用了检查再设置(CAS)的机制。这个命令的返回值是一个数组,其中的每个元素分别是原子化事务中的每个命令的返回值。 当使用 WATCH 命令时,如果事务执行中止,那么 EXEC 命令就会返回一个 Null 值。
DISCARD -> 清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。如果使用了 WATCH 命令,那么 DISCARD 命令就会将当前连接监控的所有键取消监控。这个命令的返回值是一个简单的字符串,总是 OK。
WATCH -> 当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的。这个命令的返回值是一个简单的字符串,总是 OK。对于每个键来说,时间复杂度总是 O (1)。
以下演示了 watch 乐观锁 的示例,(1) 当一个客户端 (A) 对一个变量 (a) 进行了监听此时 a = 3 并开启了事务,另一个客户端 (B) 改变了 a 的值 a = 4,那么 (A) 客户端执行完事务后,exec 会返回 nil (null) ,(2) 如果没有竞争,则正确执行。
watch 一定是和事务一起使用才有效。
UNWATCH -> 清除所有先前为一个事务监控的键。如果你调用了 EXEC 或 DISCARD 命令,那么就不需要手动调用 UNWATCH 命令。这个命令的返回值是一个简单的字符串,总是 OK。