9.redis锁

1.悲观锁:认为什么时候都会出问题,做什么操作都会加锁
    
2.乐观锁:很乐观,认为什么时候都不会出问题,更新数据时去判断一下,再此期间是否有人更改了这个数据!
MULTI(开启事务)/DISCARD(放弃事务)
使用watch 监视
使用案例1:模拟100块钱花去20块钱
        127.0.0.1:6379> set money 100(设置总钱数:100)
            OK
        127.0.0.1:6379> set out 0(设置花去的钱:0)
            OK
        127.0.0.1:6379> WATCH money(监视money:拿到money的值)
            OK
        127.0.0.1:6379> MULTI(开启事务)
            OK
        127.0.0.1:6379> DECRBY money 20(总钱数花去20)-->执行前,会比较最新的money值和watch拿到的是否一致!不一致意味着其他线程对其做了更改,就会执行失败
            QUEUED
        127.0.0.1:6379> INCRBY out 20(花去的钱增加20)
            QUEUED
        127.0.0.1:6379> exec(执行事务)
            1) (integer) 80(返回剩余的钱)
            2) (integer) 20(返回花去的钱)
        127.0.0.1:6379> get out(获取花去的钱数:20)
            "20"
        127.0.0.1:6379> get money(获取剩余的钱数:80)
            "80"
            
乐观锁导致的事务执行失败:
    两个线程:(起了两个redis客户端,同时对money做操作)
        线程1:做money的-2操作和out的+2操作
        线程2:在线程1的事务还没有exec时,更改money值为100
        线程1:
            127.0.0.1:6379> watch money
                OK
            127.0.0.1:6379> MULTI
                OK
            127.0.0.1:6379> DECRBY money 2
                QUEUED
            127.0.0.1:6379> INCRBY out 2
                QUEUED
            注意:这时线程1还没有执行exec
        线程2:
            127.0.0.1:6379> set money 1000(将money置为1000)
                OK
        这时;
            线程1:最后执行事务,返回nil,发现事务执行失败
                127.0.0.1:6379> EXEC
                    (nil)
                127.0.0.1:6379> get money(发现money置为1000)
                    "1000"

    解决方案:
        127.0.0.1:6379> UNWATCH(先解锁)
            OK
        127.0.0.1:6379> WATCH money(重新获取锁,得到money的最新值,在进行上述的+-操作)
            OK

 

posted @ 2022-05-25 21:31  努力的达子  阅读(51)  评论(0编辑  收藏  举报