zoukankan      html  css  js  c++  java
  • 【Redis分布式锁底层实现】

    我是廖志伟,一名Java开发工程师幕后大佬社区创始人Java领域优质创作者CSDN博客专家。拥有多年一线研发经验,研究过各种常见框架中间件的底层源码,对于大型分布式微服务、三高架构(高性能高并发高可用)有过实践架构经验。

    博主:java_wxid
    社区:幕后大佬



    本文的大概内容:

    一、如何实现

    redis使用setnx作为分布式锁,在多线程环境下面,只有一个线程会拿到这把锁,拿到锁的线程执行业务代码,执行业务代码需要一点时间,所以这段时间拒绝了很多等待获取锁的请求,直到有锁的线程最后释放掉锁,其他线程才能获取锁,这个就是redis的分布式锁的使用。

    二、使用redis锁会有很多异常情况,如何处理这些异常呢

    1.redis服务挂掉了,抛出异常了,锁不会被释放掉,新的请求无法进来,出现死锁问题

    添加try finally处理

    2.服务器果宕机了,导致锁不能被释放的现象

    设置超时时间

    3.锁的过期时间比业务执行时间短,会存在多个线程拥有同一把锁的现象

    如果有一个线程执行需要15s,过期时间只有10s,当执行到10s时第二个线程进来拿到这把锁,会出现多个线程拿到同一把锁执行。

    续期超时时间,当一个线程执行5s后对超时时间续期10s,续期设置可以借助redission工具,加锁成功,后台新开一个线程,每隔10秒检查是否还持有锁,如果持有则延长锁的时间,如果加锁失败一直循环(自旋)加锁。

    4.锁的过期时间比业务执行时间短,锁永久失效

    如果有一个线程执行需要15s,过期时间只有10s,当执行到10s时第二个线程进来拿到这把锁,会出现多个线程拿到同一把锁执行,在第一个线程执行完时会释放掉第二个线程的锁,以此类推,导致锁的永久失效。

    给每个线程都设置一个唯一标识,避免出现程序执行的时间超过设置的过期时间,导致其他线程删除了自己的锁,只允许自己删除自己线程的锁

    三、代码

    /**
     * 分布式锁底层实现原理
     * @return
     */
    @GetMapping("distributedLock")
    public Object distributedLock(){
        String lockKey = "distributedLockKey";
        //给每个线程都设置一个唯一标识,避免出现程序执行的时间超过设置的过期时间,导致其他线程删除了自己的锁
        String clientId = UUID.randomUUID().toString();
        try {
            //添加过期时间保证线程运行到一半的时候,程序崩了,导致缓存中的key一直存在
            Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS);
            if (!result) {
                return "error_code";
            }
            // Todo 实现业务逻辑
            redisTemplate.opsForValue().set(TestConstant.KEY_TEST,String.valueOf(System.currentTimeMillis()));
        } finally {
            //判断是不是自己的线程删除自己的锁
            if (clientId.equals(redisTemplate.opsForValue().get(lockKey))) {
                redisTemplate.delete(lockKey);
            }
        }
        //Todo 当前代码未实现锁续命功能,锁续命功能:由于程序执行时间可能超过设置缓存中锁的过期时间,导致后续一部分业务未执行,一直被其他线程抢占,需要对锁进行续命,但是由于续命的时间不好确定,这个时候就需要单独开启子线程,定时任务不断的去判断当前锁,还在不在,如果不在了,说明业务已经执行完成了,如果还在,重新设置过期时间,一般而言,定时任务的时间为缓存设置的过期时间三分之一就可以了。
        return "end";
    }
    

    总结

    以上就是今天要讲的内容,分布式锁保证了数据的准确性,但是减低了并发能力,同一个锁key,同一时间只能有一个客户端拿到锁,其他客户端会陷入无限的等待来尝试获取那个锁,只有获取到锁的客户端才能执行业务逻辑。还希望各位读者大大能够在评论区积极参与讨论,给文章提出一些宝贵的意见或者建议,合理的内容,我会采纳更新博文,重新分享给大家。


    提示:以下都是资源分享,求个一键三连。

    博客封面

    首先我要说声抱歉,作为一个学习的平台,封面引人注目是营销策略,大家不用太过在意哈,专注博客内容本身即可。当然有同学惦记着我博客的封面,这里也分享出来给大家。
    点击:博客封面
    提取码:2021

    面试资料

    福利大放送,我就求个一键三连,拜托了,这对我真的很重要。
    点击:面试资料
    提取码:2021

    200套PPT模板

    福利大放送,我就求个一键三连,拜托了,这对我真的很重要。
    点击:200套PPT模板
    提取码:2021

    提问的智慧

    福利大放送,我就求个一键三连,拜托了,这对我真的很重要。
    点击:提问的智慧
    提取码:2021

    一键三连

    感谢大家的支持,用心写博文分享给大家,你的支持(点赞收藏关注)是对我创作的最大帮助。
    微信公众号:南北踏尘
    主页地址:java_wxid
    社区地址:幕后大佬

    给读者大大的话

    我本身是一个很普通的程序员,放在人堆里,除了与生俱来的盛世美颜、所剩不多的发量,就剩下180的大高个了。就是我这样的一个人,默默坚持写博文也有好多年了,有句老话说的好,牛逼之前都是傻逼式的坚持。希望自己可以通过大量的作品,时间的积累,个人魅力、运气和时机,可以打造属于自己的技术影响力。同时也希望自己可以成为一个懂技术懂业务懂管理的综合型人才,作为项目架构路线的总设计师,掌控全局的团队大脑,技术团队中的绝对核心是我未来几年不断前进的目标。

    点击关注博主

    点击关注博主:幕后大佬
    点击关注博主:java_wxid
    点击关注社区:幕后大佬

  • 相关阅读:
    centos7.6 使用yum安装mysql5.7
    解决hadoop本地库问题
    docker-compose 启动警告
    docker 安装zabbix5.0 界面乱码问题解决
    docker 部署zabbix问题
    zookeeper 超时问题
    hbase regionserver异常宕机
    (转载)hadoop 滚动升级
    hadoop Requested data length 86483783 is longer than maximum configured RPC length
    zkfc 异常退出问题,报错Received stat error from Zookeeper. code:CONNECTIONLOSS
  • 原文地址:https://www.cnblogs.com/javawxid/p/15644354.html
Copyright © 2011-2022 走看看