redis的事务

实现

redis> MULTI
OK
redis> SET name "xingdong"
QUEUED
redis> GET name
QUEUED
redis> SET author 'Action'
QUEUED
redis> GET author
QUEUED
redis> EXEC
1) OK
2) "xingdong"
3) OK
4) "Action"

ps:事务队列以先进先出的方法保存入队的命令。

watch命令监视数据库键
实现
redis> watch name author
OK

带有 WATCH 命令的事务会将客户端和被监视的键在数据库的 watched_keys 字典中进行关联, 当键被修改时, 程序会将所有监视被修改键的客户端的 REDIS_DIRTY_CAS 标志打开。
只有在客户端的 REDIS_DIRTY_CAS 标志未被打开时, 服务器才会执行客户端提交的事务, 否则的话, 服务器将拒绝执行客户端提交的事务。

判断事务是否安全
判断事务是否安全,服务器会会根据这个客户端是否打开了REDIS_DIRTY_CAS标识来决定是否执行事务

事务的ACID性质

1.原子性

对于redis的事务功能来说,事务队列中的命令要么就是全部执行,要么就是一个都不执行。

redis的事务和传统的关系型数据库事务的最大区别在于,Redis不支持事务回滚机制。即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止。

2.一致性

事务具有一致性指的是,如果数据库在执行事务之前是一致的,那么在事务执行之后,无论事务是否执行成功,数据库也应该仍然是一致的。

a.入队错误

如果一个事务在入队命令的过程中,出现了命令不存在,或者命令的格式不正确等情况,那么redis将拒绝执行这个事务。

ps:redis2.6.5以前的入队错误处理,这种情况是被忽略的。

例子:

MUTI

set msg 'hello'

xingdong//

get msg

EXEC

此时服务器会拒绝执行入队过程中出现的事务。

b.执行错误

执行过程中发生的错误都是一些不能再入队时被服务器发现的错误,这些错误只会在命令实现执行时被触发。

即使在事务的过程中发生了错误,服务器也不会中断事务的执行,它会继续执行事务中余下的命令,并且已经执行的命令不会被出错的命令影响。

例子

set msg 'hello'

MULTI

sadd fruit 'apple' 'banana' 'cherry'

rpush msg 'see you' 'bye' //****

sadd language 'php' 'python'

EXEC

这里的出错命令不会对数据库做任何修改,但不会对事务的一致性产生认识影响。

c.隔离性

事务的隔离性指的是,即使数据库中有多个事务并发执行,各个事务之前也不会互相影响,并且在并发状态下执行的事务和串行执行的事务产生的结果完全相同。

因为redis是使用单线程的方式来执行事务(以及事务队列中的命令),并且服务器保证,在执行事务期间不会对事务进行中断,因此,redis 的事务总是以串行的方式运行的,并且事务也总是具有隔离性的。

d.持久性

redis的持久性

当服务器运行在AOF持久化模式下,并且appendfsync选项的值为always时,程序总会在执行命令之后调用同步sync函数,将命令数据真正的保存到硬盘里面,只有这种配置下的事务具有持久性的。(并且no-appendfsync-on-rewrite配置是关闭的)

下面这种做法可以保证事务的耐久性,不过效果太低,不具有实用性。

redis> MULTI

OK

redis> SET name "xingdong"

QUEUED

redis> SAVE

QUEUED

redis> EXEC

1) OK

2) OK

内容来自:<redis设计与实现>这本书