首页技术文章正文

分布式锁-Redis实现【黑马大数据培训】

更新时间:2022年12月21日 18时25分28秒 来源:黑马程序员论坛

黑马中级程序员课程

  分布式锁
  为什么需要有分布式锁呢,在单点的时候synchronized 就能解决,但是服务拆分之后,每个服务都是单独的机器,无法解决,所以出现了分布式锁,其实也就是用各种手段,实现获取唯一锁,别人无法得到。
  其实在做分布式锁的前提,需要先明白,synchronized  为啥不能使用了,啥原理让他在一个机器上可以使用。

      synchronized 的原理   
      众所周知 Synchronize 关键字是解决并发问题常用解决方案,有以下三种使用方式:
同步静态方法,锁的是当前 Class 对象。同步块,锁的是 {} 中的对象。 同步普通方法,锁的是当前对象。
  实现原理:   JVM 是通过进入、退出对象监视器( Monitor )来实现对方法、同步块的同步的。
  具体实现是在编译之后在同步方法调用前加入一个 monitor.enter 指令,在退出方法和异常处插入 monitor.exit 的指令。
  其本质就是对一个对象监视器( Monitor )进行获取,而这个获取过程具有排他性从而达到了同一时刻只能一个线程访问的目的。
  而对于没有获取到锁的线程将会阻塞到方法入口处,直到获取锁的线程 monitor.exit 之后才能尝试继续获取锁。
可以通过使用 javap -c Synchronize 可以查看编译之后的具体信息 ,这里我就不再粘贴了。
所以可以知道,单独的Java虚拟机是可实现锁的,但是多台手就伸不到了,只能在依赖外部的形式去产生一个唯一锁。
以上是参考别人的博客拿到的信息,亲自试用得到,准确   :链接:https://www.jianshu.com/p/2ba154f275ea

  Redis实现的分布式锁
  主要是利用了redis的set NX的原理,以及对redis的script脚本原子性利用。(个人看法,其实后面一步就看各自的程序逻辑如何去判定到底要不要这一步了)
  简单的说一下主要流程:
首先设置一个全局唯一的key和一个唯一性的value(value是一个解锁的保障,删除之前判断一下值是否一致)使用Redis的set 方法 以多参数形式配置key,value,nx,px,过期时间 (参数 NX:只有键不存在时,才能对其进行设置操作)利用Redis的script脚本来对key的删除操作,只能自己删除自己的value(删除之前先判断一下value是否是我之前的value,是否被改过,没有就删了)    这是脚本的主要 内容 if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else  return 0 end      对其解释: 根据 get 获取到 key 的值 ,判断key的值是否跟你传的值相等,相等则 执行del  key 否则返回0 结束    对此推荐去看一下redis的Lua脚本,给个简单的:http://redisdoc.com/script/eval.html   在实际场景中可以利用AOP的切点切面形式,实现具体是什么地方需要分布式锁,搭配分布式锁,再搭配注解方式,来实现想要的自定义设置那里需要就点哪里   AOP的主要实现是 @pointcut 切注解类在使用@around环绕对前后做处理前面加锁后面解锁del  使用script脚本   
  代码主要实现   注解类 DistributedLock [url=][/url] @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic @interface DistributedLock {    /**     * 自定义形式添加你对分布式锁的对外配置属性       * 例如:key的规则,锁的超时时间,获取锁的等待时间,等一系列的属性配置     *      */}[url=][/url]   切面类 DistributedLockAspect[url=][/url] @Aspect@Componentpublic class DistributedLockAspect {         /**     * 层切点     */    @Pointcut("@annotation(com.creditease.hardess.common.annotation.DistributedLock)")    public void distributedLockAspect() {}/**     * @param joinPoint 切点     * @return Object 添加分布式锁后,实际调用业务逻辑部分代码的返回值     * @throws Throwable 产生的所有异常,为了避免对异常处理流程产生干扰,所有异常都应该继续抛出     */    @Around("distributedLockAspect()")    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {     /**      *主要写一些锁的获取,和业务逻辑执行,锁的删除等      *     */     return returnObject;    }   /**     * 获取 DistributedLock 注解     *      * @param joinPoint     * @return 代码中定义的注解     * @throws NoSuchMethodException     */    private static DistributedLock getDistributedLock(ProceedingJoinPoint joinPoint)            throws NoSuchMethodException {        String methodName = joinPoint.getSignature().getName();        Class<?> classTarget = joinPoint.getTarget().getClass();        Class<?>[] par = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();        Method objMethod = classTarget.getMethod(methodName, par);        return objMethod.getAnnotation(DistributedLock.class);    }}}[url=][/url]

推荐了解热门学科

java培训 Python人工智能 Web前端培训 PHP培训
区块链培训 影视制作培训 C++培训 产品经理培训
UI设计培训 新媒体培训 软件测试培训 Linux运维
大数据培训 智能机器人软件开发




传智播客是一家致力于培养高素质软件开发人才的科技公司“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。

传智播客从未停止思考

传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”

中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。

何为中高级程序员课程?

传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。




黑马程序员热门视频教程

Python入门教程完整版(懂中文就能学会) 零起点打开Java世界的大门
C++| 匠心之作 从0到1入门学编程 PHP|零基础入门开发者编程核心技术
Web前端入门教程_Web前端html+css+JavaScript 软件测试入门到精通


分享到:
在线咨询 我要报名
和我们在线交谈!