Java面试专题-redis篇分布式锁

二、分布式锁

1.使用场景

  • redis分布式锁,是如何实现的?

需要结合项目中的业务进行回答,通常情况下,分布式锁使用的场景:

集群情况下的定时任务、抢单、幂等性场景

例:抢券场景:

/ **
*抢购优惠券
*@throws InterruptedException
*/

public void rush ToPurchase() throws InterruptedException {
    //获取优惠券数量

    Integer num = (Integer) redisTemplate.opsForValue().get("num");
    //判断是否抢完
    if (null == num || num <= 0) {
    throw new RuntimeException(“优惠券已抢完”);

    }
    //优惠券数量减一,说明抢到了优惠券

    num = num - 1;

    //重新设置优惠券的数量
    redis Template.opsForValue().set("num", num);
}

抢券执行流程:

1.正常情况下:

alt

2.库存只剩1个的情况

超卖情况(库存 -1)

alt

3.先使用synchronied锁
public void rush ToPurchase() throws InterruptedException {
    synchronized (this){
        //查询优惠券数量
        Integer num = (Integer) redisTemplate.opsForValue().get("num");
        //判断是否抢完
        if (null == num || num <= 0) {
        	throw new RuntimeException("商品已抢完");
        }
        //优惠券数量减一(减库存)
        num = num - 1;
        //重新设置优惠券的数量
        redisTemplate.opsForValue().set("num", num);
    }
}

alt

如果项目是单体项目,并且只启动了一台服务,这个代码就没有问题。

4.服务集群部署

但是一般为了满足并发请求,会把服务网做成集群部署。

alt

每个服务都有各自的JVM,解决不了多个JVM下线程的互斥

alt

所以在这种情况下,要使用外部的锁来解决——分布式锁

alt

2.实现原理(setnx, redisson)

redis分布式锁:

1.setnx

redis实现分布式锁主要利用redis的setnx命令。setnx是SET if not exists(如果不存在,则SET)的简写。

  • 获取锁:

    # 添加锁,NX是互斥、EX是设置超时时间
    SET lock value NX EX 10
    
    • 一条命令保证原子性

    • 不设置超时时间可能会导致死锁

  • 释放锁:

    # 释放锁,删除即可
    DEL key
    

alt

  • redis实现分布式锁如何合理的控制锁的有效时长?

    根据业务执行时间预估(不太合适)

    给锁续期 ---> redisson

2.redisson

加锁成功之后,另开一个线程进行监控

手动释放锁

public void redisLock() throws InterruptedException {
    //获取锁(重入锁),执行锁的名称
    RLock lock = redissonClient.getLock( s: "heimalock");
    //尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位
    //boolean isLock = lock.tryLock(10,30, TimeUnit.SECONDS);
    boolean isLock = lock. tryLock ( time: 10, TimeUnit. SECONDS);
    //判断是否获取成功
    if (isLock) {
        try {
        	System.out.println("执行业务”);
        } finally {
        	//释放锁
        	lock. unlock();
        }
    }
}

加锁、设置过期时间等操作都是基于lua脚本完成

alt

重入
  • redisson实现的分布式锁是否可以重入呢?

可以,要判断是不是同一个线程,是就可重入

public void add 1(){
    RLock lock = redissonClient.getLock("heimalock");
    boolean isLock = lock.tryLock();
    //执行业务
    add2();
    //释放锁
    lock.unlock();
}
public void add2(){
    RLock lock = redissonClient.getLock("heimalock");
    boolean isLock = lock.tryLock();
    //执行业务
    //释放锁
    lock.unlock();
}

利用hash结构记录线程id重入次数

KEY VALUE
field value
heimalock thread1 2
主从一致性
  • redisson实现的分布式锁能保证主从数据的一致吗?

    当主节点还没来得及同步数据,他挂了,宕机,那么依据redis的哨兵模式,他会在从节点中选择一个当作主节点

    这时候,两个线程同时持有一把锁,不满足互斥性了,可能会出现脏数据

alt

所以,提出红锁

RedLock(红锁):不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁**(n/2+1)**,避免在一个redis实例上加锁。 alt

一般不常使用:实现复杂!性能差!运维繁琐!

redis整体集群是AP思想 (高可用)

如果要保证强一致,建议使用CP思想的zookeeper

总结

  • redis分布式锁,是如何实现的?

​ ● 先按照自己简历上的业务进行描述分布式锁使用的场景 ​ ● 我们当使用的redisson实现的分布式锁,底层是setnxlua脚本(保证原子性)

  • Redisson实现分布式锁如何合理的控制锁的有效时长?

    在redisson的分布式锁中,提供了一个WatchDog(看门狗),一个线程获取锁成功以后,WatchDog会给持有锁的线程续期(默认是每隔10秒续期一次)

  • Redisson的这个锁,可以重入吗?

    可以重入,多个锁重入需要判断是否是当前线程,在redis中进行存储的时候使用的hash结构,来存储线程信息和重入的次数

  • Redisson锁能解决主从数据一致的问题吗

    不能解决,但是可以使用redisson提供的红锁来解决,但是这样的话,性能就太低了,如果业务中非要保证数据的强一致性,建议采用zookeeper实现的分布式锁

#计算机有哪些岗位值得去?##简历中的项目经历要怎么写##牛客解忧铺#
java面试专题学习记录 文章被收录于专栏

开始看黑马Java面试,27届的,大家有什么建议欢迎来说哟

全部评论
哇,你对Redis分布式锁的理解真的很深入呢!👍 在项目中使用分布式锁确实能解决很多并发问题。我有个小问题,如果我们项目中遇到锁过期了但是业务还没执行完的情况怎么办呢?😖 对了,如果你对Redis分布式锁还有其他疑问,或者想要了解更多细节,可以点击我的头像,给我发私信哦,我们可以一起深入探讨~🐮🎉 另外,Redisson真的很好用呢,它的看门狗机制真的很智能,能够帮助我们自动续期,减少死锁的风险。你对Redisson的其他特性也感兴趣吗?我们可以聊聊它的其他用途和优势哦!🤔🌟
点赞 回复 分享
发布于 今天 00:12 AI生成

相关推荐

从年头开始,就一直在忙忙碌碌,背八股,投简历,找实习。我人生的第一场面试是腾讯的实习岗面试,大概是三月份吧,那时候我lc几乎就没怎么刷,八股也是被的稀稀拉拉。一上来面试官还没让做自我介绍就甩了五道编程题给我做,但我一道都不会做,他没有开摄像头,我看着空白的函数段和在屏幕中那个窘迫的我,手心一直在冒汗,过了大概25分钟,他问我遇到了什么问题,我说“不好意思面试官,这里面的题,我哪一道都没有思路”就这样,我说完本次面试唯一的一句话后,结束了这场面试,关闭会议后我坐在电脑屏幕前发呆了很久,其实也没有感到难过,只是大脑一片空白后面也陆陆续续收到其他的一些面试,然后我不知道我哪来的自信,我就偏偏要去大厂,投递的全是叫得上名儿的大厂,结果不是笔试没过就是面试中答不上来,但是后面所有的面试官都很好,会耐心的指出我的不足或者可以改进的地方,让我每次面试后都有所进步。到了四月末,为了不拖我秋招的进度,我在boss上也开始投递一些中厂,然后顺利地拿到了offer,但我清楚的知道,我不属于那里,我不是没有资格去更高的平台,只是我还没有准备好而已。五月份我一个人从佛山出发,坐动车到了深圳这座城市,租到了满意的房子,买了一口小电锅,开始我的实习生活。深圳真的很奇幻,一边是密密麻麻的城中村,回家走在路上感觉能被电鸡创死,一边是高楼耸立的CBD,全是英文牌坊的商场,感觉每一次出地铁口都是在开盲盒。我开始逐渐适应一个人的生活,一个人自己给自己做饭,一个人吃烤肉,无聊的时候一个人去唱k,去逛展,甚至用dy开游戏直播,但有时候也会半夜emo躺床上在某个瞬间觉得自己咋这么惨入职第一天,看到自己工位上挂着“前端开发实习生-XXX”的时候,有一种不真实的感觉,我咋就开始上班了,像小孩儿装大人一样,第一个月收到工资还觉得哇撒好多,后面就在想快快给我涨工资。整个实习大概持续了三个月半吧,这里非常感谢我的mt,他不仅制定了简而有序的培养方案,还在工作与生活上给予了我非常多的支持,最开始的一个月,那个规划表里面真的是按天为单位去罗列我要干什么的,我完成一项就在上面打一个勾然后mt帮我去检验成果,后面他就慢慢放手,提醒我要开始进行思维的转换,要开始学着主动,自己去沟通,有风险只要及时暴露给他,他帮我兜底。这段时间我真的成长非常快,不仅仅是敲代码,像业务流程,技术选型,排查问题,遇到需要跨团队解决问题的能力都有所提升,到后面我好像就是一个“正式员工”了,干的还算不错,+2说如果转正要给我涨工资。mt经常与我one&nbsp;one一些我在工作上暴露的一些问题和他看到我进步的地方,真的是亦师亦友,从入职欢迎的那一顿饭到最后我离职欢送的那一段饭,前前后后我的mt请我吃了得五六顿饭了,平日也是带着我和前端同事一起吃饭,希望我能够在大家面前多刷刷脸,告诉我同事之间的关系也很重要,他忙的时候会给我发消息给我推荐哪里好吃。mt最后一次跟我one&nbsp;one就是我提离职准备秋招了,他希望我能够留下来,问我的意愿是怎么样的。“我还是说想去到一个更好的平台发展”他笑着点点头,和我们最后一顿饭碰杯一样说道“预祝你顺利拿到大厂offer,前程似锦”在公司的最后一天晚上,mt帮我记录了我在公司的最后几个瞬间,拍了好多照片,我带着这段回忆和经历重返了校园不知道大家有没有这种感觉&nbsp;,实习或者工作后回到学校会觉得不真实,好像自己已经离开了很久了不再属于这里了,外面被拷打了一番感觉岁月静好哈哈,回来去测mbti,从i/enfp变成了esfp?所以本就持怀疑态度的我再也信这玩意儿了。短暂歇了一段时间就开始准备秋招了,诚实讲相比于准备实习,秋招的整个阶段都比较浮躁,不知道是八股滚了一遍又一遍的原因还是时间线确实太长了,面试前其实不想做太多的复习。但是心态上就比实习那时候更加的平和,能过就过,不过拉倒,基本上有面试的中大厂一面都可以过,就是在二面上栽跟头。说实话秋招除了能力真的挺看运气的,看合不合面试官眼缘,问的问题是不是刚刚好都会答,但是越努力越幸运嘛,还是得在每次面试后总结面经,然后相应得拓宽自己的知识范围。期间加了几个秋招群,发现应聘大厂的真的是人才扎堆,硕士满天,92横飞,很担心最后横向自己的履历比不过别人。面试期间比较抓马的一幕是,我携程(上海)已经hr面后泡了1个月了,然后我在面哈啰的时候一个021(上海)开头的电话打过来,我以为是oc电话,但是又出于对面试官的尊重没有马上接听,面试结束后赶紧打了过去,结果是之前在boss上面投递的另外一家公司的笔试提醒......好在几天后携程真的打过来了,真是命运捉弄秋招人,没想到是秋招的第一家面的公司最后给到了offer,这时候已经接近12月了,终于是松了口气结束了秋招。最后总结一下吧,感觉写到这里回头看写的就像流水账,其实从选方向到实习到秋招,我非常感谢我坚持了我自己认为对的事情,身边没有一个同学选择前端,但是我觉得用户能直接与我做的界面流畅交互让我觉得有成就感,我也喜欢好看的东西,我乐意与UI打交道,我选择了。对于我拒绝了实习转正,别人也不明白明明待遇还不错为什么还要离开,我选择了。在我实习和秋招在大厂面试吃瘪的时候,有时会收到一些质疑,我选择继续,实习不行秋招,秋招不行春招。希望在未来,我也能坚持自己的想法,大步向前。
牛客80849854...:看完了,真不容易夸夸自己吧太棒了您
2025年终总结
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务