• Redis事务及锁应用



    Redis只支持简单的事务,不像mysql那样比较完整严格,对数据的完整性也维持的很好。redis的开启事务实际上只是将开启事务之后的一段命令用队列
    包裹起来了,当调用redis的执行命令(exec)全部执行在队列中的命令。
    一、mysql事务与redis事务的比较

     

       

    Mysql

     
     

    Redis

     
     

    开启

     
     

    start transaction

     
     

    multi

     
     

    语句

     
     

    普通sql

     
     

    普通命令

     
     

    失败

     
     

    rollback 回滚

     
     

    discard 取消

     
     

    成功

     
     

    commit

     
     

    exec

     


    二、redis事务一般使用演示
    (1).先清空所有数据
    127.0.0.1:6379> flushdb
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> set t1 "test1 value"
    QUEUED
    127.0.0.1:6379> set t2 "test2 value"
    QUEUED
    127.0.0.1:6379>
    (2).当没有执行提交的时,打开另外一个redis命令窗口执行keys *发现并没有新的数据产生
    127.0.0.1:6379> keys *
    (empty list or set)
    (3).在窗口一种执行提交
    127.0.0.1:6379> exec
    1) OK
    2) OK
    (4).另一窗口显示所有key
    127.0.0.1:6379> keys *
    1) "t1"
    2) "t2"

    三、redis事务若是出错并不回滚
    redis事务命令列中如果出错,整个事务并不回滚,而是会继续执行下去,所以这就违反了事务中ACID特点的原子性
    redis事务出错的两种情况:
    (1).redis语法有问题导致出错
    执行exec后的结果:所有multi后执行的命令都不会被执行

    演示如下:
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> set a a
    QUEUED
    127.0.0.1:6379> set b
    (error) ERR wrong number of arguments for 'set' command
    127.0.0.1:6379> exec
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379>
    查看最终结果key:
    127.0.0.1:6379> keys *
    1) "t1"
    2) "t2"
    总结:并没有找到multi后执行的命令结果key,说明全部失败了

    (2).redis语法没问题但是操作的适用对象有问题,比如sadd(设置set类型的值)操作string类型的key
    执行exec的结果:除了redis语法操作的命令不被正确执行,其它不会被影响正常执行(这个是属于程序级别的出错,一般是由程序员控制的)
    演示如下:
    127.0.0.1:6379> flushdb
    OK
    127.0.0.1:6379> set num1 3
    OK
    127.0.0.1:6379> set num2 4
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> incrby num1 3
    QUEUED
    127.0.0.1:6379> sadd num2 2
    QUEUED
    127.0.0.1:6379> exec
    1) (integer) 6
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    查看最终结果:
    127.0.0.1:6379> mget num1 num2
    1) "6"
    2) "4"
    127.0.0.1:6379>
    总结:因为num1,num2都是字符串类型,multi后用sadd操作num2类型错误,而最终执行后只是num2执行失败,num2正常的由数字3增加了3变成了六。

    四、redis的锁机制
    悲观锁:如果我去买票,我会想世界不和谐,肯定有人跟我抢,我先把票锁起来,只有我能够操作,这就是悲观锁
    乐观锁:如果我去买票,哎呀没那么多人买票,还有好多的票了,所以不用上锁,我只需要关注最后剩下多少张票就行了,这就是乐观锁
    演示如下
    127.0.0.1:6379> keys *
    (empty list or set)
    如果售票点有1张票,自己手上还有100块钱
    127.0.0.1:6379> set ticket 1
    OK
    127.0.0.1:6379> set money 100
    OK
    127.0.0.1:6379> mget ticket money
    1) "1"
    2) "100"
    我们先给ticket(票)加锁
    127.0.0.1:6379> watch ticket
    OK
    开始执行事务
    127.0.0.1:6379> multi
    OK
    这个时候火车站只有一张余票了,我发起了两张票的请求
    127.0.0.1:6379> decrby ticket 2
    QUEUED
    扣除80块的票钱
    127.0.0.1:6379> decrby money 80
    QUEUED
    开始执行提交
    127.0.0.1:6379> exec
    报错了
    (error) EXECABORT Transaction discarded because of previous errors.
    查看结果没有变化因为票只有一张不够所以整个事务保持原有的结果
    127.0.0.1:6379> mget ticket money
    1) "1"
    2) "100"
    unwatch取消所有锁监听
    127.0.0.1:6379> unwatch
    OK
    总结:redis的事务中,启用的是乐观锁,只负责事务中key没有被改动。

  • 相关阅读:
    30行代码让你理解angular依赖注入:angular 依赖注入原理
    图片上传插件ImgUploadJS:用HTML5 File API 实现截图粘贴上传、拖拽上传
    HTML5 Application cache初探和企业应用启示
    使用idea的groovy脚本自动创建Jpa的实体
    使用idea的groovy脚本自动创建MybatisPlus的实体
    判断汉字和英文
    PostgreSQL 字符串分隔函数(regexp_split_to_table、regexp_split_to_array)
    golang实现文字云算法
    Java中的String真的无法修改吗
    使用asyncio实现redis客户端
  • 原文地址:https://www.cnblogs.com/lisqiong/p/5553437.html
Copyright © 2020-2023  润新知