Redis入门(六)——Redis事务

Redis入门(六)——Redis事务


 目录:

  • redis事务简介
  • redis事务的使用
  • 小结

1.redis事务简介

事务指的是可以一次执行多个命令,本质是一组命令集合,一个事务中的所有命令都会序列化,按顺序的串行化执行而不会被其他命令插入。银行转账就是最经典的事务场景之一。

redis事务用于一个队列中,一次性,顺序性。排他性的执行一系列命令。

传统的关系型数据库如mysql,oracle中的事务需要满足ACID四个特性。即:

原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。
一致性(consistency):事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。
隔离性(isolation)一个事务的执行不能被其他事务所影响。

持久性(durability):一个事务一旦提交,事物的操作便永久性的保存在DB中。即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

而redis数据属于典型的Nosql数据库。不需要满足ACID四个特性。Nosql数据库满足CAP三个特性其中之二。CAP即:

强一致性(Consistency):在任意时刻,所有的分布式节点中的数据是一样的。

可用性(Availability):分布式系统中某一个服务在某台或者多台台服务器出问题后,在其他服务器上依然能够完成用户的操作。

分区容错性Partition torerance):在出现网络分区(比如断网)的情况下,分离的系统也能正常运行。

2.redis事务使用

下表列出了 redis 事务的相关命令:

命令 描述 用法
MULTI 标记一个事务块的开始

MULTI

标记一个事务开始,后面是一系列事务操作。

EXEC 执行所有事务块内的命令

EXEC

在一系列事务操作后使用该命令,执行所有事务块内的命令。

DISCARD 取消事务,放弃执行事务块内的所有命令

DISCARD

在一系列事务操作后使用该命令,放弃执行事务块内的所有命令

WATCH 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

WATCH key [key ...]

UNWATCH 取消 WATCH 命令对所有 key 的监视。 UNWATCH

MULTI命令实例:

 只要符合redis语法规范的命令均可入队。

放弃事务实例:

事务执行失败实例:

 当事务中有一个命令执行失败,其他命令会执行成功吗?下图为实际操作的实例:

可见,redis事务中要么全部执行成功,要么全部执行失败。可是前文不是说不满足原子性吗,这里岂不是满足原子性。上图中出现了我胡乱加的一个命令abc k7 v7,也就是说该命令不满足redis语法规范。那如果是满足redis语法规范的语句,在redis事务中执行失败,其他合法命令会怎么样呢?下图演示了该场景下的操作情况。

 其中,k1是一个string类型的数据,执行incr命令会不通过,但是由于符合语法规范,该语句不会报错,仍然显示加入队列中。当我们执行EXEC命令来执行整个事务的时候后,可见incr k1执行失败,而其他可以执行的语句并不受影响。可见redis事务不满足原子性。

WATCH监控:

在介绍WATCH命令之前先说明下redis中的乐观锁悲观锁的概念以及CAS。

悲观锁:每次器拿数据的时候都认为该数据会被修改,所以每次拿到数据后都会对该数据上锁,保证自由自己操作该数据。等本次获取的锁释放后其他操作方可获得该锁。

乐观锁:每次器拿数据的时候都认为该数据不会被修改,所以不会上锁,但是下更新该数据的时候回判断下别人有没有更新该数据,通常使用版本号的机制。即每次修改数据后对该数据价格版本号,其他人在修改该数据前先对比下该数据的版本号有没有变化。一般实际场景中使用的是乐观锁。

下面以信用卡可用余额与欠额的场景说明WATCH的应用。

首先来看没有加塞的场景,WATCH balance,然后在一个事务中减少balance增加debt,执行EXEC命令后,可见事务执行成功。

 再来看有加塞的场景,首先还是WATCH balance,然后另外开启一个redis连接。修改balance的值,再回到第一个redis连接上,执行之前的事务操作,该事务操作是否会执行成功,请看下面的操作实例

 UNWATCH命令:

执行UNWATCH,取消 WATCH 命令对所有 key 的监控。注意,一旦执行了EXEC命令,之前加的监控锁都会被取消。

3.小结

WATCH指令类似于乐观锁,事务提交时,如果key的值已经被别的客户改变,比如某个list已被别的客户端push/pop过了,整个事务都不会被执行。

通过WATCH命令在事务执行之前监控了多个key,倘若在WATCH之后有任何key的值发生变化,EXEC命令执行的事务都将被放弃,同时返回Nullmuti-bulk应答已通知调用者事务执行失败。

猜你喜欢

转载自www.cnblogs.com/zylhxd/p/11439247.html