• Java中的锁和分布式架构中的锁


    悲观锁和乐观锁

            指在要对数据冲突的时候,面对的一种态度。

            悲观锁,默认我修改数据的时候别人也会去修改。常见的解决方法利用数据库的行锁。

            乐观锁,对数据冲突持有乐观态度,操作数据的时候不会加锁,只有在数据提交的时候才会去验证数据的状态。常见的解决方案是用加版本号或者时间戳的方式来解决。以及CAS操作。

            偏向锁

            可重入锁

            互斥锁

            读写锁

            公平锁

            悲观锁

            CAS自旋锁。存在的问题消耗性能CPU,而且还有旋不出来的可能

    JVM锁

            Synchronized和Lock锁

            公平锁:严格按照请求顺序来竞争锁资源。

            非公平锁:允许插队来竞争锁资源。

            ReetrantLock 和Synchronized 默认非公平锁
       

            ReetrantLock内部使用AQS同步队列。AQS队列是一种FIFO的双向等待队列。

            公平锁的实现是线程加入的时候会先去检测AQS里面有没有等待线程,如果没有则执行,有则加入到队尾。非公平锁的实现是一进来就会去抢占锁,抢占不到就会到AQS里面去等待。公平锁的策略会有一个内核态的切换,会影响性能。但非公平锁则会在上一个线程快要释放资源的时候就去抢占了锁,减少了因内核态切换的性能时间的等待。提升了锁竞争的效率。

            new ReetrantLock(boolea fair);

            传入true的时候创建公平锁,默认是false,创建非公平锁。

    分布式锁

            经典的例子。库存数量的扣除,需要引入分布式锁。

    为什么要使用分布式锁?

            分布式锁所解决的是有多个线程或进程去访问一个共享资源的时候带来的一个安全性问题。

            锁的用途分为两种锁。一种是共享锁,一种是排他锁。

            共享锁是允许多个线程或进程去访问同一资源。这样一个核心点是可以适用一个幂等性的场景中,避免因为重复加锁而带来的一个性能的开销

            排他锁则是在同一时间内只允许一个访问者来访问该资源,其它访问者则被拒绝。比较适合在非幂等性的场景中来适用。

            目前实现分布式锁的常用中间件有redis和zookeeper两种

    基于Redis

          1. setnx命令:指定的key不存在时,为key设置值。指定的key存在时返回0

           2.使用Redssion。用封装好的api Lock()和unLock()去实现锁的抢占和释放。而Redssion是用Lua脚本去实现的,可以保证执行所有指令的原子性。另外Redission里面还有一个watchdog,看门狗。它会在获取锁以后,每隔10s去帮你的key做一个自动续约,从而去避免锁的过期。

    基于Zookeeper

           用zookeeper去实现分布式锁的方法比较多。

            1.使用有序节点的方法。每个线程/进程都到zookeeper的lock目录下去创建一个临时有序节点,去表示抢占锁,所有创建的节点都会按照创建的先后顺序去生成一个带有编号的节点,线程创建之后,获取/Lock节点下面的所有子节点,去判断当前线程创建的节点是否是所有节点里面序号最小的,如果当前线程创建的节点是所有节点里面最小的,那么我们认为他是获得锁成功,如果当前创建的节点不是所有节点里面最小的,我们需要对当前线程创建的前一个节点去做一个事件监听,当被监听这个节点被释放后,则产生一个回调告诉当前线程,从而尝试再次去抢占锁。这就是zookeeper基于有序节点实现分布式锁的原理。

            对比Redis和Zookpeer两种分布式锁。redis是获取不到锁则需要不断的进行尝试,会对性能造成很影响。第二个Redis是个AP模型,在集群环境中很容易出现数据一致性,很容易会导致锁出现问题,即便是使用redLock这种算法来实现分布式锁,在某写复杂的场景下也无法保证锁的百分之百可用。不过在实际开发中,使用redis来实现分布式锁还是比较常见的。一般也不会遇到一些极端复杂的场景,更重要的是redis的性能也是比较高的,所以在高并发场景下是会比较合适一些。

            对于zookeeper来说,zookeeper天生就是一个分布式协调组件,他是一个cp模型,更适合实现分布式锁,对于zookeeper来说,如果获取不到锁,只需要添加一个监听器就行了,不用一直去轮询,所以性能消耗会比较小,如果在两者之间来做选择的话,zookeeper会更好一些。

  • 相关阅读:
    奇异值和零空间
    【java爬虫】使用selenium获取某交易所公司半年报数据
    电子行业库存管理痛点与WMS仓储管理系统解决方案
    java装饰器设计模式
    Web服务器-Tomcat详细原理与实现
    快手资讯 | 快手前CEO宿华业务助理彭佳瞳、商业算法策略负责人李勇保被曝离职
    RapidEye快鸟、SPOT卫星遥感影像数据
    【数据可视化Python库】
    学习JAVA的第六天(基础)
    果然AIGC还是对动漫制作下手了,不过是从数据集AnimeRun开始
  • 原文地址:https://blog.csdn.net/qq_16298769/article/details/127644429