事务在执行时,会提供专门的属性保证,包括
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
Redis 如何实现事务?
事务的执行过程包含三个步骤,Redis 提供了 MULTI、EXEC 两个命令来完成这三个步骤
- 第一步,客户端要使用一个命令显式地表示一个事务的开启:MULTI 命令
- 第二步,客户端把事务中本身要执行的具体操作(例如增删改数据)发送给服务器端。这些操作就是 Redis 本身提供的数据读写命令,例如 GET、SET 等。不过,这些命令虽然被客户端发送到了服务器端,但 Redis 实例只是把这些命令暂存到一个命令队列中,并不会立即执行。
- 第三步,客户端向服务器端发送提交事务的命令,让数据库实际执行第二步中发送的具体操作。Redis 提供的 EXEC 命令就是执行事务提交的。当服务器端收到 EXEC 命令后,才会实际执行命令队列中的所有命令。
Redis 的事务机制能保证哪些属性?
原子性
Redis 中并没有提供回滚机制
只有当事务中使用的命令语法有误时,原子性得不到保证,在其它情况下,事务都可以原子性执行
- DISCARD 命令:只能用来主动放弃事务执行,把暂存的命令队列清空,起不到回滚的效果
- MULTI 和 EXEC 配合使用不能保证原子性
- 队列中的命令,因类型不匹配导致失败,仅当前命令执行失败,不影响其他命令执行
举例
- 命令入队时就报错,会放弃事务执行,保证原子性;
- 命令入队时没报错,实际执行时报错,不保证原子性;
- EXEC 命令执行时实例故障,如果开启了 AOF 日志,可以保证原子性。
一致性
隔离性
WATCH 机制的作用是,在事务执行前,监控一个或多个键的值变化情况,当事务调用 EXEC 命令执行时,WATCH 机制会先检查监控的键是否被其它客户端修改了。如果修改了,就放弃事务执行,避免事务的隔离性被破坏。然后,客户端可以再次执行事务,此时,如果没有并发修改事务数据的操作了,事务就能正常执行,隔离性也得到了保证。
持久性
不管 Redis 采用什么持久化模式,事务的持久性属性是得不到保证的
留言区
为什么Redis不支持回滚?
Redis 官网文档 Why Redis does not support roll backs?
- 只有当事务中使用的命令语法有误时,原子性得不到保证
- 回滚并不能避免编程错误
- 不支持回滚实现更简单、高效