联想软开暑期实习 一面
一、问题
刚说了MySQL事务,说一下Redis是否支持ACID
我:balabal....
面试官:中间原子性说错了
注:以下为一些不太完整的总结。
二、Redis事务
1、事务ACID
事务是一系列严密的逻辑操作,可以使一条SQL语句也可以是一组,是恢复和并发控制的基本单元。
ACID指一致性,原子性,隔离性,持久性。
原子性:事务中的多个操作必须度完成,或者都不完成。
一致性:数据库中的数据在事务执行前后状态是一致的。
隔离性:数据库执行该事务的时候,不受其他事务影响。
持久性:事务对数据的修改持久化保存。
其中在MySQL中一致性是最终追求的目标,隔离性由锁机制实现,原子性和持久性由redolog和undolog保证。
2、Redis如何实现事务
Redis通过命令开启和提交事务,和命令队列的形式支持事务
- MULTI开启事务。
- 提交redis数据操作命令到命令队列中,不会立即执行。
- EXEC提交事务,实际执行队列中的命令。
3、Redis事务机制保证哪些属性
(1)原子性:
- 第一种情况,执行EXEC命令前,客户端发送的命令本身有错误,比如语法问题或者本身命令不存在,这些命令入队就检测出来错误。后续即使添加正确命令,执行EXEC命令提交事务也会失败。保证原子性。
- 第二种情况,错误命令入队redis未检查出来,比如命令和操作数据不符,这是会把正确命令执行完,错误命令无法执行,因而命令队列中的所有命令只执行了一部分事务无法保证原子性。同样在命令入队之后,如果发现命令有错,提供DISCARD命令可以主动放弃事务执行,清空命令队列。
- 第三种情况,执行EXEC命令,redis故障,导致执行失败。如果开启了AOF日志记录命令,就可以恢复并不执行事务操作,保持原子性,如果未开启日志,则无法保证。
也就是说:
- 如果命令入队就报错,会放弃事务,保证原子性
- 如果命令入队没报错,实际执行报错,不保证原子性
- EXEC命令执行时候故障,如果开启了AOF日志,则保证原子性
(2)一致性:
- 命令入队就报错,事务会被放弃,保持一致性
- 执行才报错,错误的命令不执行,正确的命令执行,也保证一致性
- 执行EXEC命令redis发生故障。如果记录了日志,可以清除事务操作,如果没记录日志,那么就可以恢复到事务执行前的状态,也是保持一致性。
(3)隔离性
分两种情况:
- 并发操作在EXEC命令执行前,要使用WATCH机制保证隔离性,否则无法保证。
- 并发操作在EXEC后,可以保证
WATCH机制可以再事务执行前监控一个或者多个键的值变化情况,如果执行EXEC事务,WATCH机制会检查监控的键是否被其他客户端修改了,就放弃事务,避免被破坏隔离性。
如果没有WATCH机制,可能直接开启事务的命令读取的数据,在事务未提交之前,其他事务可能就修改该数据,提交事务读取的数据不一致了。
(4)持久性
无论是什么持久化模式,由于是内存数据库,掉电宕机,都无法保证修改的数据化持久化属性。
4、总结
4个命令支持事务
redis事务机制可以保证一致性和隔离性,无法保证持久性,但是对于redis而言,本身是内存数据库,所以持久化不是必须属性。
原子性需要自己进行检查,尽可能保证。