美文网首页Redis学习
Redis 事务详解

Redis 事务详解

作者: 十年磨一剑1111 | 来源:发表于2020-04-16 10:34 被阅读0次

    类似于结构化数据库(MySQL,SQL Server 等),Redis也有事务,不过两者会不太一样。下面来简单聊下redis事务,下面的实验是在单机的redis上测试的,redis的版本是5.0.7。

    特点:

    1. 不支持回滚(一般结构化事务是支持回滚的),但是在另外一个角度看是相对简洁和快速的。
    2. 在事务中的操作不会返回执行的结果,而是返回queued(命令被加入队列,并参与排队等待执行)。
    3. 如果事务里面只要有一条命令有语法错误,exec命令就不会执行。
    4. 如果事务中的命令出现的是运行错误,比如使用散列类型的命令操作集合类型的键,由于这种错误在实际执行前Redis是没法发现的,所以在事务里面这样的命令是会被接受且执行的,其他的命令也会执行(包括出错命令之后的命令)。
    5. Redis事务在执行过程中并不会阻塞其他连接的并发,而只是通过比较watch监控键值对去保证数据一致性,如果没有发生变化,那么它会执行事务队列中的命令。如果有发生变化,那么它不会执行任何事务中的命令。这个时候只能重新执行失败的事务。

    对于语法错误和运行错误这两种错误小伙伴们可以亲自测试下,这里不做展示了

    在了解完Redis事务的几个特性后,下面我们来分析两个场景来帮助理解:
    场景1:比如用户A想关注用户B,也就是用户的关注和被关注的关系,如果使用Redis存储这样的关系可以使用集合类型。思路是对每个用户使用两个集合user:1:followers和user:1:following,分别用来存储关注该用户的用户集合和该用户关注的集合,如果在执行完第一条命令后由于某种原因导致第二条命令没法执行,就会出现用户A的粉丝有用户B,但是用户B的关注列表确没有用户A,这个时候就会想到事务。

    redis>multi
    OK
    redis>sadd user:1:followers 2
    QUEUED
    redis> sadd user:2:following 1
    QUEUED
    redis>exec
    1) (integer) 1
    2) (integer) 1
    

    当然这也要看是出现什么类型的错误,如果是语法错误,使用事务完全是没有问题的,但是如果出现的是运行错误,这种错误使用事务就不行了,但是这种类型的错误也不是完全不能避免,例如我们可以规范键的命名等。
    场景2:我们了解到Redis事务中的命令执行是不会返回执行结果的,如果我们的业务是要根据上一个命令的结果来进行后面的操作,这个时候使用事务就达不到要求,但是我们又要防止竞态的发生,这个时候我们可以使用watch来解决,watch命令可以监控一个或多个键,一旦其中一个键被修改或者删除,之后的事务就不会执行。执行exec命令后会取消对所有键的监控。
    下面来实际操作下,来帮助理解watch命令

    redis>set height 180
    OK
    redis>watch height
    OK
    redis> set height 170
    OK
    redis> get height
    170
    redis> multi
    OK
    redis>set height 185
    QUEUED
    redis>set age 87
    QUEUED
    redis>exec
    (nil)
    redis>get age
    "29"          //之前设置的值
    redis>get height
    "170"   //之前的值
    redis>set height 190
    OK    //事务提交后设置成功了
    redis>get height 
    "190"  
    

    如果在事务之前watch了一个key,并且watch操作后修改了这个key,在后面的事务中也对这个key进行了修改(或者删除)操作,那么这个事务是不会执行成功的。当执行完exec后所有的watch会被释放,这个时候就可以对key进行设置。有小伙伴可能会想如果我事务里面没有操作被watch(监控)的key呢?

    redis> set color blue
    OK
    redis> watch color   //监控键color
    OK
    redis> set color green
    OK
    redis> get color
    "green"
    redis> multi
    OK
    redis> set car 1 // 修改键car 而不是键color
    QUEUED
    redis> exec
    (nil)       //执行不成功
    

    结果发现在事务中修改其他的key也不行,这个时候只能重新执行该事务,也就是说watch发现被监控的key被修改后,这个修改操作后的事务都不会执行成功,不论是否是修改当前被watch的key。

    需要注意:watch命令只是当被监控的键值被修改后阻止之后一个事务的执行,而不能保证其他客户端不能修改这一键值,关于这一点这里就不展示具体的操作了,小伙伴们如果有不理解的地方可以多测试下。

    先聊到这,有需要补充的小伙伴可以在下面和我留言哦,看到会及时回复的。

    相关文章

      网友评论

        本文标题:Redis 事务详解

        本文链接:https://www.haomeiwen.com/subject/ezvcvhtx.html