Redis - 事务

一、概述


和传统关系型数据库一样,Redis 同样是支持事务的。Redis 的事务可以通过 MULTI/EXEC/DISCARD/WATCH 等命令来实现。

 

二、事务的 ACID 特性


1). 原子性:事务中的命令要么全部执行,要么都不执行。

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

那么不支持回滚对 Redis 来说有何优势:不需要支持回滚,Redis 内部可以保证简单而快速。

不支持回滚是否合理:合理,事务队列中的命令在执行过程中,只会因为命令错误的语法而失败,而失败的命令是编程造成的,这些错误应该在开发过程中被发现,而不应该出现在生产环境中。

 

2). 一致性:数据库在事务执行之前是一致的,在事务执行后无论事务执行成功还是失败,数据库都应该是一致的。

“一致” 指的是数据符合数据库本身的定义和要求,没有非法或者无效的错误数据。Redis 通过谨慎的错误检测和简单的设计保证事务的一致性(详看本页:四)

 

3). 隔离性:各个事务之间不会相互影响,在并发状态下和在串行状态下执行事务的结果完全相同。 

4). 持久性:当事务执行完毕后,结果保存到数据库中不会丢失。

  • 无持久化机制下,事务部具有持久性:服务器停机重启后数据丢失。
  • RDB 机制下,在特定条件下才会保存数据集快照,不能保证数据在第一时间被保存在硬盘中。
  • AOF 机制下,appendfsync = always 时,程序总会在执行命令之后调用同步函数,将命令数据存在硬盘中,这种情况下的事务具有持久性。
  • AOF 机制下,appendfsync = everysec 时候,程序会每秒同步一次数据到硬盘。因为停机可能就发生在命令执行完毕但是尚未同步的那一秒钟内,这样会造成事务数据丢失,故而不具有持久性。
  • AOF 机制下,appendfsync = no,由操作系统决定何时将数据同步到硬盘。因为事务数据可能在等待同步的过程中丢失,这样会造成事务数据丢失,故而不具有持久性。

 

三、相关命令的用法


1). MULTI 与 EXEC:MULTI 用于开启事务,总是返回 ok。MULTI 执行后,后面的命令暂时不会执行,而是会存到队列中,等到 EXEC 执行之后,队列中的命令才会依次序执行。例子如下:

 

2). DISCARD 始终返回 ok,会清空事务队列,并且放弃执行事务。例子如下:

 

3). WATCH 命令(想看本页:五)

 

 

四、Redis 怎样处理事务中的错误


Redis 怎样处理事务中的错误来保证数据库的 “一致性” :

1). 入队错误

可能原因:命令不存在,命令格式不正确等

处理方式:Redis 会对入队失败的命令进行记录,当调用 exec 的时候,自动拒绝执行并放弃这个事务。

例子如下:INCR mykey 1 入队失败,因为命令格式不正确。

 

2). 执行错误

可能原因:命令语法错误(入队时无法检测,只有在执行的时候才会报错,比如事务中处理集合的命令用在了字符串上面)。

处理方式:事务中的命令执行失败,继续执行下一条命令,直至事务队列中的命令执行结束。

例子如下:LPOP mykey 报错,作用于 list 类型,不能用于字符串;但是不影响后续命令执行,+1 操作依然执行成功。

 

3). 服务器停机

  • 如果服务器运行在无持久化的模式下,那么重启后的数据库是空白的,空白的数据库总是一致的。
  • 如果服务器运行在 RDB 模式下,可以利用现有的 RDB 文件还原数据库到一个一致的状态。若 RDB 文件找不到,那么重启后的数据库是空白的,空白的数据库总是一致的。
  • 如果服务器运行在 AOF 模式下,可以根据现有的 AOF 文件来恢复数据,将数据库还原到一个一致的状态。若 AOF 文件找不到,那么重启后的数据库是空白的,空白的数据库总是一致的。

综上所述,服务器停机不会影响数据库一致性。

 

五、WATCH 命令与乐观锁


WATCH 命令的返回值总是为 ok。

WATCH 命令本身就是一个乐观锁,它可以在 EXEC 命令执行之前,监视一定数量的 key,并在 EXEC 执行时,检查这些 key 是否被修改过,如果是的话,服务器就拒绝执行事务。例子如下:

时间 客户端A 客户端B
T1 WATCH  name  
T2 MULTI  
T3 SET  name  aa  
T4   SET  name  bb
T5 EXEC  

客户端 A 执行事务的时候发现 name 的值被修改了,所以服务器拒绝执行这个事务。

 

如何取消对 key 的监视:

  • WATCH 对 key 的监视从调用 WATCH 开始生效,直到调用 EXEC 为止。EXEC 被调用的时候不管事务是否执行,都会取消对 key 的监视。
  • 另外当客户端断开连接后也会取消监视。
  • 使用无参数的 UNWATCH 可以取消对所有 key 的监视。
posted @ 2017-08-23 20:32  PointNet  阅读(321)  评论(0编辑  收藏  举报