redis系列(十):事务
redis有事务么?
redis官方说是有事务的。但这个事务不是我们普遍理解的mysql事务。
-
redis的事务不支持回滚,一组命令一起执行,前一个失败不影响后面执行,后面失败前面也不会回滚
-
redis事务只是把事务中的所有命令入队列,当commit的时候统一执行。只是执行的时候,隔离其他操作。因为redis是单线程,这个隔离也好实现。
事务的实现
一个事务从开始到结束通常会经过三个阶段
- 事务开始
- 命令入队
- 事务执行
事务开始
以multi命令开始
multi
事务入队
redis对每个事务会创建一个队列,先进先出队列,将事务中的命令全部放入队列中
事务执行
以exec命令来提交事务
exec
过程就是队列中的命令一条一条执行。只是被一起执行了,其实互不影响。
事务可能出错的地方
入队错误
如果一个事务在命令入队的过程中,出现了命令不存在,或者命令格式不正确等情况,那么redis在执行exec的时候,会拒绝整个事务。
执行错误
执行错误,redis事务中的各个命令互不影响
服务器停机
因为redis有持久化,所以服务器停机,在停机之前执行的命令都执行了,停机之前未执行的命令,不会被执行。
事务的ACID特性
原子性
定义:事务中的多个操作当做一个整体来执行,要么都执行,要么都不执行。
因为一个事务中的操作,相互不影响,所以严格意义上来说,不满足原子性。
一致性
定义:事务之前数据是一致的,事务之后数据也是一致的
不以业务为主,redis满足一致性了,因为数据就不可能不一致。当有业务介入的时候,就不满足一致性了,还是因为没有回滚,A转账给B,A成功,B失败,前后整体的钱数不一致了。
隔离性
定义:数据库中多个事务并发的执行,各个事务之间不会互相影响,并且在并发状态下执行和串行执行的结果是完全相同的。
redis是单线程操作的,所以有天生的隔离机制,redis服务端保证在执行事务期间不会对事务进行中断,所以,redis事务总是串行执行的。具备隔离性。
持久性
定义:当一个事务执行完毕,执行这个事务所得到的结果被保存在持久化存储中,即使服务器在事务执行完成后停机了,执行的事务的结果也不会丢失。
- 纯内存运行,不具备持久化,服务器一旦停机,数据都丢失
- RDB模式持久化。触发了RDB就满足持久化。
- AOF模式持久化。得看aof策略,完全同步刷脏页就满足持久化。
watch命令
watch命令是一个乐观锁。在exce命令执行前,监视数据库的键,在exec执行时,如果所监视的key但凡有一个被修改了,服务器就拒绝整个事务。
时间 | 客户端A | 客户端B |
---|---|---|
T1 | watch "name" | |
T2 | multi | |
T3 | set "name" "peter" | |
T4 | set "name" "john" | |
T5 | exec |
当客户端A执行exec的时候,因为name在事务入队期间被客户端B修改了,所以服务器拒绝客户端A的的事务。
redis隔离性是,在exec执行期间,别的客户端不能执行命令,但事务入队期间是可以的,这也是watch的作用所在。