1 事务概述
Redis事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中的所有命令都会被序列化。在事务执行过程中会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入事务执行命令序列中。
multi、exec、discard、watch是Redis中事务的基础,它们允许一步执行一组命令,并确保以下两点:
1、事务中的所有命令都被序列化并按顺序执行。在Redis事务的执行过程中永远不会穿插另一个客户端发出的请求,这样可以确保将事务中的所有命令作为独立操作来执行。
2、所有命令要么都被处理,要么都不被处理,因此Redis的事务具有原子性。EXEC命令会触发事务中所有命令的执行。使用AOF时Redis会确保使用单个write操作将事务写入磁盘。如果Redis服务器宕机,则可能禁止性了服务器宕机期间的部分操作。Redis将在重新启动时检测到这种情况,而后退出并显示错误信息。使用redis-check-aof工具可以修复AOF文件,删除该文件中的事务部分,这样服务器就可以重新启动了。
相关命令说明如下:
watch key:监听一个或多个键,如果在事务执行之前被监听的键被其他客户端改动了,则事务被打断。
multi:标记一个事务块的开始。
exec:执行事务块内的所有命令。
discard:取消事务,放弃事务块中的所有命令。
Redis事务可以一次执行多个命令,并且带有以下三个重要的保证。
1、在发送exec命令之前批量命令被放入队列中缓存。
2、收到exec命令后事务开始执行,如果事务中的任意命令执行失败,其余的命令依然会被执行(前提是命令没有编译型错误)。
3、在事务执行过程中哦该,其他客户端提交的命令请求不会插入当前事务执行的命令序列中。
2 事务使用
2.1 事务的三个阶段
开启:以multi开启一个事务。
入队:将多个命令加到事务中,事务接到这些命令后并不会立即执行,而是放到等待执行的事务队列中。
执行:由exec命令触发事务的执行。
2.2 事务举例
1、事务执行命令如下:
2、事务的取消
以下是取消事务执行命令:
3 事务失败:出现错误的命令
当事务队列的命令存在编译型错误时,还未执行exec命令就报错,则事务会成功回滚,整个事务中的命令都不会提交。这就是Redis事务中的入队错误。
如果一个事务在命令入队过程中出现了命令不存在或者命令格式不正确等情况,Redis将拒绝执行这个事务。
4、事务失败:语法错误
当事务出现“v1 +1 ”语法错误的时候,事务除了错误的命令没有执行外,其余都被执行成功,并未出现回滚。这就是Redis事务中执行错误命令的情况。
除了命令在入队时可能发生错误以外,事务还可能在执行过程中发生错误,比如一些不可能在入队时被服务器发现的错误,这些错误只会在命令实际执行时被处罚。即使在事务的执行过程中发生错误,服务器也不会中断事务的执行,它会继续执行事务中余下的其他命令,并且已执行的命令不会被出错的命令所影响。
5 使用watch
如果客户端1监听number1之后开启事务,在此过程中客户端2修改number2,此时客户端1提交该事务,那么事务提交会失败。
watch命令类似乐观锁,在事务提交时,如果watch监听的多个键中任何一个键的值已被其他客户端修改,那么使用exec执行事务时命令将不会被执行。
3 事务性质
在传统的关系型数据库中,经常用ACID(原子性、一致性、隔离性、持久性)来校验事务功能的安全性和可靠性。在Redis中,事务总是具有原子性、一致性、隔离性,并且当Redis运行在某个特定的持久化方式时,还具有持久性。
3.1 原子性
事务的原子性是指,数据库事务中的多个命令作为一个整体来执行,服务器要么执行事务中的所有命令,要么一个命令也不执行。Redis事务队列中的命令要么全部执行,要么一个都不执行,同样具有原子性。
Redis的事务和传统的关系型数据事务的最大区别在于,Redis不支持事务回滚机制。这种做法的优点是:Redis命令只会因为错误的语法而失败,或是命令用在了错误类型的键上。也就是说,从实用性的角度来讲,失败的命令是由变成错误造成的,而这些错误应该在开发的过程中被发现,不应该出现在生产环境中。
因为不需要支持回滚,所以Redis内部的运行可以保持简单且快速。
3.2 一致性
事务的一致性指的是,如果数据库在执行事务之前是一致的,那么在事务执行之后无论事务是否执行成功,数据库仍然应该是一致的。Redis通过谨慎的错误检查和简单的设计来保证事务的一致性,因为在事务执行的过程中出现的错误命令会被服务器识别出来,并进行相应的错误处理,所以这些出错的命令不会对数据库进行任何修改,也不会对事务的一致性产生任何影响。
3.3 隔离性
事务的隔离性指的是,即使数据库中有多个事务并发执行,各个事务之间也不会相互影响。并且在并发状态下进行的事务和串行状态下执行的事务产生的结果完全相同。
因为Redis使用单线程(执行命令的线程只有一个)的方式来执行事务,并且服务器保证在执行期间不会中断事务,Redis的事务总是以串行的方式执行,因此事务也具有隔离性。
3.4 持久性
事务的持久性指的是,当一个事务执行完毕时,执行这个事务所得的结果已经被保存到硬盘中,即使服务器在事务执行完毕之后停机,执行事务的结果也不会丢失。
因为Redis的事务不是简单地用列队包裹了一组Redis命令,Redis并没有为事务提供任何额外的持久化功能,所以Redis的事务耐久性由Redis所使用的持久化模式决定。