分布式缓存Redis之事务

来源:互联网 发布:竞彩代购软件 编辑:程序博客网 时间:2024/05/22 04:31

写在前面

  本学习教程所有示例代码见GitHub:https://github.com/selfconzrr/Redis_Learning
  事务特性官方文档:https://redis.io/topics/transactions
  事务特性中文文档:http://www.redis.cn/topics/transactions.html

  从redis2.6开始引入Redis script,将来有可能取代Redis transaction

  关系型数据库的事务具备:原子性(A)、一致性(C)、隔离性(I)、持久性(D)。在Redis中也同样拥有事务的概念。

Redis事务的使用

  Redis中与事务相关的命令有5个,分别是:MULTI EXEC DISCARD WATCH UNWATCH

  1)MULTI命令用于开启事务:

  开启事务后,可以开始对键执行操作。能看到开启事务后命令的返回都是”QUEUED”,Redis Server收到这些命令后将他们保存在队列中,只有收到EXEC命令才会真正执行

  这里写图片描述

  2)EXEC命令:当在exec之前使用watch命令的话,只有被watch的key没有被修改的情况下,exec命令才会真正执行(类似于乐观锁optimistic lock)(案例见(4)),exec的返回结果是一个Array结构的数据,其中每个元素是事务中顺序执行的命令的结果

  3)当执行了MULTI命令和一些操作后,想放弃当前事务,可以使用DISCARD命令,DISCARD命令会清空事务命令队列,并退出事务(注意discard并不是rollback回滚)。

  4)WATCH命令:监控一个或者多个key,如果这些key在提交事务(EXEC)之前被其他用户修改过,那么事务将执行失败,需要重新获取最新数据重头操作(类似于乐观锁)。使得Redis事务具有check-and-set(CAS)语义,WATCH命令用法:

  客户端1

  这里写图片描述

  客户端2

  这里写图片描述

  上述命令中:Client1对count使用WATCH命令后开启事务,在执行EXEC命令前,Client2修改了count的值,Client1执行EXEC命令会失败。

  5)UNWATCH:取消WATCH命令对所有key的监控,所有监控锁将会被取消。

Redis事务的特性

  1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
  2. 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行
  3. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行(比如出现下面的错误类型二),没有回滚机制

在Redis事务中会出现两类错误:

  • 命令语法错误、参数错误等,命令没有进入事务的命令队列,直接就返回错误。
  • 命令进入事务的命令队列,但在执行EXEC后出错,例如对错误的数据类型使用了不支持的操作。

  客户端可以在事务提交前就感知到第一类错误,一般客户端在收到第一类错误时会discard当前事务,当执行EXEC命令时返回:(error) EXECABORT Transaction discarded because of previous errors。比如:

  这里写图片描述

  在第五条命令中我随便打了几个字符,提交事务的时候并没有成功,这也很符合我们对事务的理解。从图中可以看到错误命令在我输入的时候就已经报错了,也就是说这条错误命令在进入队列的时候redis就已经知道这是一条错误命令,这样,整个事务的命令将全部失败,那么,有没有一种可能某个错误指令在进入队列的时候redis还没有发现他的错误呢?比如:

  这里写图片描述

  这就是我们上面提到的第二类错误,对于一个存在问题的命令,如果在入队的时候就已经知道其出错,整个事务内的命令将都不会被执行(其后续的命令依然可以入队),如果这个错误命令在入队的时候并没有报错,而是在执行的时候出错了,那么redis默认跳过这个命令执行后续命令。也就是说,redis只实现了部分事务(并不能保证事务的原子性)

—–乐于分享,共同进步
—–Any comments greatly appreciated
—–诚心欢迎各位交流讨论!QQ:1138517609