ACID概念
A:原子性:要求一个事务是不可再分的,要么全部发生,要么全部不发生;
C:一致性:要求事务执行前后不改变数据库的状态,例如不应该执行后把错误的数据写入其中;
I:隔离性:事务A在未提交之间做的修改对于事务B应该是不可见的,不能读到互相未提交的内容;
D:持久性:要求数据是可持久化的,也即是数据是不易丢失的;
Redis中事务的体现
Redis中事务的开启使用的是 MULTI,提交使用的是 EXEC,在这两个命令之间的命令都会被存入一个命令队列中,只有提交后才会依次执行。
与MySQL不同的是,在入队的时候Redis就会对命令的语法格式进行校验,如果是不合法的语句就会报错,提交时所有命令都会失败;此外Redis并不会对命令语句的合法性做判断,例如对String键进行列表操作是不会在入队时报错的,只会在提交时报错,但其他命令会正常执行。
Redis到底有没有保证ACID
① 原子性
如果从整体上看,Redis的事务中的命令都是在队列中取出来依次执行的,那么原子性应该是可以保障的,但如果是出现语句操作不恰当,那么其他正常语句还是会执行,并且Redis中并没有回滚的机制,这就会给人一种不原子的感觉。我觉得从广义上来看,Redis的事务是支持原子性的,因为其作者也提到过,对于这些语句上的错误(非语法)在客户端传入的时候就应该检查,而不是依赖于Redis的检查,因此Redis也选择不提供回滚机制,减轻负担。如果从这方面来讲,只要保证了命令操作是正确的,那么事务的原子性实际上也是可以保证的,只是并非数据库的原子概念。
② 一致性
由于命令在入队以及执行时都会有相应的检查机制,因此也不会造成不一致的情况,一致性是可以保证的。
③ 隔离性
可以使用WATCH启用对键的监控,如果检测到该键的变更,那么该事务在提交时就会整体失败,并且由于命令执行是单线程的,队列中的命令都可以保证依次执行,因此在这种环境下的隔离性是可以保证的。
④ 持久性
Redis提供RDB和AOF的持久化方案,对于RDB来说,并不是在每条命令执行时都进行记录,而是根据设置的自动save时间以及手动save来进行快照的写入;对于AOF来说,三种方案都有造成数据丢失的风险,因此无论是哪一种方案实际上都无法完全保证持久性。