• 【Redis】事务和锁机制


    一、事务的基本操作

    1、redis中事务的概念不同于Mysql数据库中的事务
    它是一个单独的隔离操作:事务中所有的命令都会序列化、按照顺序依次执行
    事务在执行的过程中,不会被其他客户端发送的命令请求打断

    Redis事务的主要作用:串联多个命令防止别的命令插队

    2、基本命令Multi、Exec、discard

    • Multi:组队命令,将命令依次放入队列中,但是不会执行
    • Exec:执行,redis将之前命令队列中的命令依次执行
    • discard:放弃,可以在组队过程中使用discard放弃组队
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> set k1 v1
    QUEUED
    127.0.0.1:6379(TX)> get k1
    QUEUED
    127.0.0.1:6379(TX)> exec
    1) OK
    2) "v1"
    127.0.0.1:6379>
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> set k2 v2
    QUEUED
    127.0.0.1:6379(TX)> get k2
    QUEUED
    127.0.0.1:6379(TX)> discard
    OK
    127.0.0.1:6379>
    127.0.0.1:6379> get k1
    "v1"
    127.0.0.1:6379> get k2
    (nil)
    127.0.0.1:6379>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3、事务的错误处理

    • 场景一:使用multi过程中,出现错误,执行时整个队列的命令都会被取消
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> set k1 v1
    QUEUED
    127.0.0.1:6379(TX)> set k2 v2
    QUEUED
    127.0.0.1:6379(TX)> set k3
    (error) ERR wrong number of arguments for 'set' command
    127.0.0.1:6379(TX)>
    127.0.0.1:6379(TX)> exec
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379>
    127.0.0.1:6379>
    127.0.0.1:6379> get k1
    (nil)
    127.0.0.1:6379>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 场景二:命令组队过程中没有出错,但是使用exec执行的过程中出错,那么只有出错的命令不会被执行,其他的命令正常执行
    127.0.0.1:6379>
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> set key1 value1
    QUEUED
    # 这里key1的value值不是数字,所以执行自增会报错
    127.0.0.1:6379(TX)> incr key1
    QUEUED
    127.0.0.1:6379(TX)> set key2 value2
    QUEUED
    127.0.0.1:6379(TX)> exec
    1) OK
    2) (error) ERR value is not an integer or out of range
    3) OK
    127.0.0.1:6379>
    127.0.0.1:6379> get key2
    "value2"
    127.0.0.1:6379>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    二、事务冲突(悲观锁和乐观锁

    1、悲观锁
    悲观锁在操作数据时比较悲观,认为别人会同时修改数据。 因此操作数据时直接把数据锁住,直到操作完成后才会释放锁,上锁期间其他人不能修改数据,从而使这个数据处于一个block的状态

    例如Mysql中的行锁与表锁等

    2、乐观锁
    乐观锁在操作数据时认为别人不会同时修改数据,所以不会对数据进行上锁

    但是在更新数据时,会去判断在此期间是否有人修改过此数据,如果有人修改那就放弃更新,可以将这个过程理解为check-and-set

    乐观锁大多是基于数据版本( Version )记录机制实现

    3、乐观锁演示
    在执行事务之前,我们可以使用watch key [key..]命令对可能同时被两个客户端修改的数据做一个监视,如果事务执行之前,这个key的值被修改,那么事务将被打断

    执行unwatch取消对所有key的监视

    客户端A

    127.0.0.1:6379>
    127.0.0.1:6379> set price 100
    OK
    127.0.0.1:6379> watch price
    OK
    127.0.0.1:6379>
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> incrby price 20
    QUEUED
    127.0.0.1:6379(TX)> exec
    1) (integer) 120
    127.0.0.1:6379>
    127.0.0.1:6379> unwatch
    OK
    127.0.0.1:6379>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    客户端B

    127.0.0.1:6379> keys *
    1) "price"
    127.0.0.1:6379>
    127.0.0.1:6379> watch price
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)>
    127.0.0.1:6379(TX)> incrby price 10
    QUEUED
    127.0.0.1:6379(TX)> exec
    (nil)
    127.0.0.1:6379>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    可以看到,客户端A对price这个key做了修改,所以客户端B在执行事务时,发现数据被修改了,无法成功执行

    三、redis事务特性

    1、单独的隔离操作

    • 事务中的所有命令都会序列化、按照顺序依次执行
    • 事务在执行过程中,不会被其他客户端发送的命令请求所打断

    2、没有隔离级别的概念

    • 队列中的命令,在提交之前都不会实际被执行

    3、不保证原子性

    • 事务执行过程中,如果有一条命令执行失败,其他命令仍然继续执行,不会回滚

    如有错误,欢迎指正!!!

  • 相关阅读:
    达梦数据库安装和使用
    VM501开发套件开发版单振弦式传感器采集模块岩土工程监测
    B+树索引的管理
    【maven】idea中基于maven-webapp骨架创建的web.xml问题
    WCF 请求答复模式
    【转】ES, 广告索引
    【uni-app从入门到实战】get请求、数据缓存、图片上传预览
    阿里面试官:给我描述一下缓存击穿的现象,并说说你的解决思路?
    Visual Studio 2010 软件安装教程(附下载链接)——计算机二级专用编程软件
    “我“眼中的测试/开发程序员,预想与现实的碰撞......
  • 原文地址:https://blog.csdn.net/Decade0712/article/details/128070977