对于Redis的事务功能来说,事务队列中的命令要么就全部都执行,要么就一个都不执行,因此,Redis的事务是具有原子性的
Redis的事务 和 传统的关系型数据库事务 的 最大区别在于,Redis不支持事务回滚机制(rollback)
即使 事务队列中的某个命令 在执行期间 出现了错误,整个事务也会继续执行下去,直到 将事务队列中 的 所有命令 都执行完毕 为止
Redis主要认为失败 都是由 使用者造成的 所以就没有回滚操作
在Redis中除了没有回滚,Redis对事务也没有隔离级别的概念,所以就不会产生在使用关系型数据库时需要关注的脏读,幻读,重复读的问题
Redis通过谨慎的错误检测和简单的设计来保证事务的一致性
如果一个事务在入队命令的过程中,出现了 命令不存在,或者 命令的格式不正确 等情况,那么Redis将拒绝执行这个事务
因为服务器会拒绝 执行入队过程中 出现错误的事务,所以Redis事务的一致性 不会被 带有 入队错误的事务 影响
根据文档记录,在Redis 2.6.5以前的版本,即使有命令在入队过程中发生了错误,事务一样可以执行,不过被执行的命令只包括那些正确入队的命令
因为错误的命令不会被入队,所以Redis不会尝试去执行错误的命令
因此,即使在2.6.5以前的版本中,Redis事务的一致性也不会被入队错误影响
除了入队时可能发生错误以外,事务还可能在执行的过程中发生错误
关于这种错误有两个需要说明的地方:
对数据库键执行了错误类型的操作是事务执行期间最常见的错误之一
如果Redis服务器在执行事务的过程中停机,那么根据服务器所使用的持久化模式,可能有以下情况出现:
因为Redis使用单线程的方式来执行事务(以及事务队列中的命令),并且服务器保证,在执行事务期间不会对事务进行中断,因此,Redis的事务总是以串行的方式运行的,并且事务也总是具有隔离性的
因为Redis的事务 不过是 简单地 用队列 包裹起了 一组Redis命令,Redis并没有为事务提供任何额外的持久化功能,所以Redis事务的持久性由Redis所使用的持久化模式决定:
BGSAVE
命令,对数据库进行保存操作,并且异步执行的BGSAVE
不能保证事务数据被第一时间保存到硬盘里面,因此RDB持久化模式下的事务也不具有持久性appendfsync
选项的值为always
时,程序 总会在 执行命令之后 调用同步(sync)函数,将命令数据真正地保存到硬盘里面,因此这种配置下的事务是具有持久性的appendfsync
选项的值为everysec
时,程序会每秒同步一次命令数据到硬盘。因为停机可能会恰好发生在等待同步的那一秒钟之内这可能会造成事务数据丢失,所以这种配置下的事务不具有持久性appendfsync
选项的值为no
时,程序 会交由 操作系统来决定 何时将命令数据同步到硬盘。因为事务数据可能在等待同步的过程中丢失,所以这种配置下的事务不具有持久性不论Redis在什么模式下运作,在一个事务的最后加上SAVE
命令总可以保证事务的持久性
配置选项no-appendfsync-on-rewrite
可以配合appendfsync
选项为always
或者everysec
的AOF持久化模式使用
当no-appendfsync-on-rewrite
选项处于打开状态时,在执行BGSAVE
命令或者BGREWRITEAOF
命令期间,服务器会暂时停止对AOF文件进行同步,从而尽可能地减少I/O阻塞
但是这样一来,关于“always模式的AOF持久化可以保证事务的持久性”这一结论将不再成立
因为在服务器停止对AOF文件进行同步期间,事务结果可能会因为停机而丢失
因此,如果服务器打开了no-appendfsync-on-rewrite
选项,那么即使服务器运行在always
模式的AOF持久化之下,事务也不具有持久性
在默认配置下,no-appendfsync-on-rewrite
处于关闭状态