亮,有一计

文章 分类 评论
52 17 10

站点介绍

这是一个热爱和别人一起交流学习的程序员所建立的个人博客 欢迎大家交流讨论

redis分布式锁

liang 2022-11-23 52 0条评论 redis深度学习 redis

首页 / 正文
本站的文章若无特殊标明转载的话均为原创,有些文章在我的csdn个人站也有,两者基本上是同步的 博客地址

发布于2022-07-08

分布式锁

分布式锁的理念

  • 独占性:任何一个时刻有且仅有一个线程持有
  • 高可用:若redis集群环境下,不能因为一个节点挂了而出现获取锁和释放锁失败的情况
  • 防死锁:杜绝死锁,必须有超时控制机制或者撤销操作,有个兜底的终止跳出方案
  • 不乱抢:防止张冠李戴,不能私下unlock别人的锁,只能自己加锁自己释放
  • 重入性:同一个节点的同一个线程如果获得锁之后,它也可以再次获取这个锁

分布式锁逐步剖析

下面的考虑都是建立在分布式锁的前提下(对于单机的锁来说的话并不是完全适用的)

单机下加锁

单机如果都没有加锁,在单价下就会导致超卖,保证不了数据的一致性

加锁解锁保证同时出现并保证调用

释放锁的代码必须放入到finally块中,保证任何情况下都会被执行

加锁必须考虑时间问题

防止加完锁后,服务可能会挂掉,导致这个锁无期限的锁下去,所以对redis分布式锁的key必须加上一个过期时间的限制

加锁和设置过期时间必须保证原子性

否则照样会出现上面的问题(要特别注意,在高并发的场景下,任何的有锁操作或者资源争用,一定要时时刻刻的警惕原子性,防止自己犯错)

张冠李戴,删除了别人的锁

第一个进来的线程自己执行的方法时间过长了,redis的key到期自动失效,这时候第二个线程进来开始加锁干活,第二个还没走完,第一个线程执行完毕,直接删掉了第二个线程的加锁key,这样的话就导致了混乱.(判断value是自己的才去删除,否则不删除)

判断锁是自己的和删除锁非原子性

这样的话你判断完的一瞬间去删除锁还是有个时间差,在高并发下很有可能你删除的锁还是不是自己的,还是会误删,所以高并发的锁相关操作一定要考虑原子性,每一步都要谨慎(采用lua脚本来保证原子性,redis对lua脚本有原生的支持,专门用来确保一系列的操作的原子性)

确保redis锁的过期时间永远大于业务执行时间

可以用看门狗 watchDog解决

redis异步复制锁丢失

redis集群是AP属性,在master和slave切换的时候有可能就造成锁的丢失(主节点还没同步给从节点,主节点就挂了,从节点升级为主节点,锁就丢失了) zookeeper集群是CP属性(zookeeper保证了一致性,整个节点都通知到才算成功,但是他牺牲了高可用性来保证的一致性)
用RedLock之Redisson落地实现解决

Redisson解决方案

分布式锁解决方案

public static String key = "redisLock";

    public String redisLock() {
        String value = UUID.randomUUID().toString() + Thread.currentThread().getName();
        RLock lock = redisson.getLock(key);
        lock.lock();
        try {
            //doSomeThing
            return "完成";
        } finally {
            //避免张冠李戴
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

RedLock

容错率公式

N(部署台数) = 2*(宕机数量)+1

设计理念

  • 获取当前时间,以毫秒为单位
  • 依次尝试从5个实例,使用相同的key和随机值获取锁.当向Redis请求获取锁时,客户端应该设置一个超时时间,这个超时时间应该小于锁的失效时间,例如你的锁自动失效时间为10秒,则超时时间应该在5-50毫秒之间,这样可以防止客户端在试图与一个宕机的Redis节点对话时长时间处于阻塞状态.如果一个实例不可用,客户端应该尽量尝试去另一个Redis实例请求获取锁
  • 客户端通过当前时间减去步骤1记录的时间来计算获取锁使用的时间,当且仅当从大多数(N/2+1)的Redis节点都获取到锁,并且获取锁使用的时间小于锁失效时间,锁才算获取成功
  • 如果获取到了锁,其真正有效时间等于初始有效时间减去获取锁所用的时间
  • 如果由于某些原因未能获取锁(至少无法在至少N/2+1个Redis实例获取锁,或者获取锁的时间超过了有效时间),客户端应该在所有的Redis实例上解锁(即使某些Redis实例根本就没有加锁成功,防止某些节点获取到锁但是客户端没有得到响应而导致接下来的一段时间不能被重新获取锁)

    该方案为了解决数据不一致的问题,直接舍弃了异步复制只使用master节点,同时由于舍弃了slave,为了保证可用性,引入了N个主节点,官方建议是5,其实一般3个也行,基本够用了

代码案例

public String getLock(){
        String value = UUID.randomUUID() + Thread.currentThread().getName();
        RLock lock1 = redissonClient1.getLock(key);
        RLock lock2 = redissonClient2.getLock(key);
        RLock lock3 = redissonClient3.getLock(key);
        RedissonRedLock redLock = new RedissonRedLock(lock1,lock2,lock3);
        boolean isLockBoolean;
        try {
            //waitTime,抢锁的等待时间
            //leaseTime就是redis的key的过期时间
            isLockBoolean = redLock.tryLock(3,300, TimeUnit.SECONDS);
            if (isLockBoolean){
                //doSomeThing
                return "true";
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            redLock.unlock();
        }
        return "false";
    }

缓存续命(watchDog)

实现原理

额外起一个线程,定期检查线程是否还持有锁,如果有则延长过期时间.Redisson里面就实现了这个方案,使用"看门狗"定期检查(每1/3的锁时间检查一次),如果线程还在持有锁,则刷新过期时间

代码跟踪

redisson的lock方法自带了看门狗,直接进行锁续命
默认值设置
1/3检查一次

lua脚本加锁解释

lua脚本解释

参数解释
KEYS[1]代表的是你加锁的那个key就是你自己设置的redis加锁的那个锁的key
ARGV[2]代表的是加锁的客户端ID锁的hash值
ARGV[3]就是锁key的默认生存时间默认30秒
如何加锁你要加锁的那个key不存在的话,你就进行加锁 hincrby 7bcf6a9f-e7f7-49b0-9727.....:117 1 接着会执行 pexpire lockzzyy 30000
  • 通过exists判断,如果锁不存在,则设置值和过期时间,加锁成功
  • 通过hexists判断,如果锁已经存在,并且锁的是当前的线程,则证明是重入锁,加锁成功(会把hash出来的那个整数值加一)
  • 如果锁已经存在,但是锁的不是当前线程,则证明有其他的线程持有锁,返回当前锁的过期时间,此时加锁失败
lua脚本解锁解释

lua解锁脚本

评论(0)

最新评论

  • manchester united tøj

    Araofclmh australia vm barn Drakt KaseyTls Kristieif real madrid drakt ThadHilly RhysHorns liverpool tröja barn DedraNett AlissaGal Maglia Chile Mondiali 2022 MilanFait OnitaSass chelsea drakt AlannahEa NaomiLev liverpool tröja barn JuanTregu AdrieneBe Brasilien VM 2022 Landsholdstrøje MilfordNe SimonJsh maglie napoli 2022 JuliaLayt EzraPouli marseille tröja LinoldDi JannieSpr chelsea matchtröja GlendaMes CraigTasm Atalanta Drakt LenaBella LashondaB Maglia Armenia Mondiali 2022 JermaineE RicoLeona danmark VM tröja Shananwsw Gildaohft VM fotbollstrojör VM CaryBrans TrenavcZ Portugal VM 2022 Landsholdstrøje JewelJano Jacquetta Island VM 2022 Landsholdstrøje FreyaYdyr TobiasHer Portugal VM 2022 Landsholdstrøje AzucenaVe BeatriceV australia VM 2022 Drakt VeronaTul MoseButtr Maglia Wales Mondiali 2022 StacyHytt TobiasHer Portugal VM 2022 Landsholdstrøje AzucenaVe

  • Hello Word !

    我发现我的评论功能,加载不了头像!朋友圈和相册也加载不了,音乐播放器也不显示,求解!

  • il: Clark11370

    Margenemh 357 fotballdrakter til bedriftslag Coreyc – Coin Media – журнал о заработке в интернете Francesco CasieDalu maglia argentina AbbieLand JessRoman Website Darrellie PaulinaRu Profile of ChristieRy SidneyMgw ToneyKrog Liverpool Tøj - Blog Profile - iotaJots JaimieChe TriciaBri Wolearn: GregoryEmelia: Magliette Calcio Poco Prezzo SheltonTh WayneHone 438 Chile Tröja Barn Leopol – Profile – Primescool Forum CharlineC VitoHartf norge bortedrakt to receive adulation, always insists the result is most important and will therefore be thoroughly disheartened by this display. As is often the case in friendly matches, there was a lack FedericoW صفحه اصلی – Maglia Porto KurtBrise of urgency for large periods during this match, though Wales did link play promisingly in attack through Wilson and Brooks. Italy will be among the nations in pot one for the Euro 2020 qualifying draw in Dublin on 2 December having drawn 0-0 against Portugal in their previous match to ensure a second-place finish in Nations League Group 3A. TanjaFitz Elizabeth manchester city tröjor KenPoulin CarenWhar Maglia Juventus Bambino EmeliaBow Stephaine liverpool drakt DarlaFulm FerneSuvg barcelona FC drakt Meaganold EmilyEise arsenal drakt KourtneyS Kellyejoh inter trøje JamaalWor Loisniyet psg drakt MaricelaS CecileSwa lavora come produttore esecutivo della serie CharissaC ChastityF Home - Liverpool Drakt EmilGmvut CasieDalu maglia argentina AbbieLand UrsulaLof rashford numero maglia KareemCap SSNGilber arsenal drakt 2022 MelodeePe

  • arsenal trøjer

    BrittnyFo atletico madrid tröja ClaritaBu ZJRBridge magliette psg JosephDur Valentina real madrid drakt MarionTol NevaLangt manchester united drakt BraydenBo RodolfoCa Real Madrid Tröja KelliefjL BettinaMi Notenbrood op top niveau MillardMh RichardMo arsenal drakt Bradleyjo TanyaNuge Spanien landsholdstrøje AprilBuck JoannaShe Billige Polen Fotballdrakter NiklasWes Maryellen terza maglia milan PrincessN AnhGiffen real madrid tröja FredricAu JoannaShe Billige Polen Fotballdrakter NiklasWes EssieOate juventus matchtröja PreciousF EdnaTippe sabinahogan447 EffieOcon MichaelaH liverpool tröja barn KayleighM JonnieHoc nuova maglia roma 2021/22 CortezSha YDZClaire ac milan drakt KathleneH CedricBac manchester united drakt Peterysjl HaicoQcmw Maglia Brasile Femmina ThereseJu DoreenMes napoli trøje JadaLanni

  • maglie hellas verona 2022

    Your style is very unique in comparison to other folks I have read stuff from. Many thanks for posting when you have the opportunity, Guess I'll just bookmark this blog. maglie hellas verona 2022 IlanaGxrn frankrike tröja JaneenZtt

日历

2023年02月

   1234
567891011
12131415161718
19202122232425
262728    

友情链接

文章目录

推荐关键字:

站点公告
本站的文章若无特殊标明转载的话均为原创,有些文章在我的csdn个人站也有,两者基本上是同步的 博客地址
点击小铃铛关闭