Redis事务与ACID属性
在web开发中,数据库是中流砥柱,一切的根基。而实际开发中,又以关系型数据库MySQL为主。MySQL数据库可以满足小项目的基本需求,但当项目数据量、并发度逐渐增大,单纯的MySQL数据库常面临庞大的性能压力。而此时,非关系型数据库Redis闪亮登场。运行在内存中的Redis数据库,简单易用,省去了磁盘IO的它,更是可以达到每秒上千万次的查询速度。而一个值得思考的问题是:如此小巧的Redis,能够支持事务吗,能够满足ACID属性吗?本文将对此一一探讨。
Redis事务
与MySQL一样,Redis同样支持事务。Redis的事务执行与一个队列相关,通过MULTI开标志一个事务块的开始,其后跟多条命令,并以一个EXEC结束并执行事务块。
如下所示:以下五行命令组成了一个事务,并向数据库中插入了三个字符串
multi
set a aaa
set b bbb
set c ccc
exec
除了MULTI、EXEC之外,Redis还支持DISCARD命令来取消事务、WATCH命令来监视一个key、UNWATCH取消监视
隔离性(Isolation)
事务的隔离性是指:多个事务在并发执行的过程中,彼此互不干扰。Redis事务在隔离性方面可以说是毫无争议的,因为Redis是单进程、单线程应用,其所有事务都将串行执行,所以不存在彼此干扰的问题。
原子性(Atomicity)
事务的原子性是指:一个事务要么全部执行成功,要么出现错误,全部失败。严格来说,Redis事务不满足原子性特性。
Redis的事务由多条命令组成,若错误是由可检查的错误,如命令拼写错误等造成的,那么事务将会彻底失败。
但若Redis事务中的错误是在执行期产生的,那么Redis会提示该命令报错,但并不回滚,其他命令依旧成功执行。因此,Redis事务不满足原子性。
Redis的开发者认为,回滚机制与Redis简单高效的设计主旨相违背,没有必要开发事务回滚功能。
一致性(Consistency)
事物的一致性是指:一个事务执行后,不破坏原数据库的完整性约束。Redis事务满足原子性要求。
为了说明这一点,必须了解可能破坏Redis事务一致性的三种错误情况:入队错误、执行错误、服务器停机。
1)入队错误:类似于上述拼写错误,会在入队时被检查出来,并导致整个事务的失败,数据库会回到事务执行前的状态,因此不破坏数据库的完整性约束。
2)执行错误:执行错误会导致该条命令失败,不会对数据库做出任何修改,所以也不影响事物的一致性
3)服务器宕机:若在事务执行的过程中,服务器出现宕机现象,其在重启后会根据rdb或aof持久化文件恢复到事务执行前的状态或者变成空白数据库,而这两种状态都是一致的
持久性(Duaration)
事务的持久性是指:当一个事务执行完毕后,该事务对数据库造成的影响会得到永久保存,即使服务器停机,也不会丢失。Redis事务时而满足持久性,时而不满足持久性,取决于其设置的持久化策略:
1)当服务器采用RDB持久化模式时,在满足一定条件时才会调用BGSAVE命令,对数据进行永久保存。若在一个事务执行后,BGSAVE命令调用前,服务器宕机,则事务结果会丢失,因此不满足持久性。
2)当服务器采用AOF持久化模式,且appendfsync设置为everysec或no时,持久化操作会每一秒执行一次或者由操作系统来决定何时执行,这都留给了服务器宕机破坏事务持久性的机会。
3)当服务器采用AOF持久化模式,且appendfsync设置为always时,每条指令的执行都将伴随持久化操作,那么此时Redis事务满足持久性。