• 锁以及分布式锁


    1、分布式锁 需要满足的要求

      1)、排他性:同一时间只会有一个客户端能获取到锁,其他客户端同时不能获取;

      2)、避免死锁:锁在一段时间后一定会被释放;

      3)、高可用:获取或释放锁的机制必须高可用且性能佳。

      实现方式:
        a、基于数据库实现 基于数据库的乐观锁:在数据库表中引入一个版本号字段。在修改数据的时候,版本号同时改变。另一个人去修改的同时,对比版本号,不一致,则操作不成功。则重新操作。 基于数据库的悲观锁:MySQL中基于for update实现,排它锁;

        b、基于Redis实现 主要是依赖Redis自身的原子操作:set user_key user_value NX PX 100 ,解锁就是删除该key。 当key不存在才会执行成功,当多个进程同时并发设置一个key,只有一个进程成功。 针对redis集群模式的分布式锁,可以采用redis的redlock机制;

        c、基于ZooKeeper实现 使用临时有序节点来实现分布式锁 具体实现还得看其他文章,这只是个大概讲解。

    2、非公平锁

      在加锁过程,线程1运行,线程2处于等待队列。 线程1运行结束,结果线程3抢先于线程2进行。这就是非公平锁的简单含义。

      在ReentrantLock lock = new ReentrantLock()默认的就是非公平锁,构造函数中加入true:ReentrantLock lock = new ReentrantLock(true)。

      公平锁原则就是线程3就绪后,会先查看等待队列是否有线程,有就排队。

    3、Redis分布式锁的底层原理

      Redis锁引入Redisson(一个开源框架)的依赖

      代码: Rlock lock = redisson.getLocl(”myLock“): 加锁:lock.lock(); 解锁lock.unlock();

      实现原理:

        1)、加锁机制:如果某个客户端要加锁,面对的是redis集群,首先会根据hash几点选择一台机器。然后发送一段lua脚本到redis上,脚本中的KEYS[1]代表加锁的key,ARGV[1]代表锁默认生存时间30秒,ARGV[2]代表客户端ID;

        2)、锁互斥机制:当客户端1访问,加锁。客户端2访问,key已经存在,会得到一个锁的剩余时间。然后进入一个while循环,不短尝试加锁。等客户端1锁释放,客户端2就会加锁;

        3)、watch dog 自动延期机制:加锁时间超过30秒,客户端1还想继续持有这把锁,那就启动watch dog看门狗,是一个后台线程,每隔10秒检查1下,如果客户端1还持有锁,就会不断延长锁key的生存时间;

        4)、可重入加锁机制:如果客户端1都已经持有这把锁,结果可重入的加锁。此时就会对客户端1的加锁次数+1;

        5)、释放锁机制:lock.unlock()是对锁数据的加锁次数-1,发现是0的时候即客户端1不再持有这把锁。客户端2此时就可以加锁了。

      在集群情况下,机器A申请到了锁L,结果A宕机,并没有同步到集群的其他机器上,可能机器B也会申请到锁L。 所以提出了红锁(RedLock)的算法:

        1)、首先生成集群中多个机器的RLock,并将其构建成RedLock;

        2)、一次对三个集群加锁,过程和普通Redis加锁一致;

        3)、如果循环加锁失败,判断失败数是否小于集群数N/2,必须保证失败数小于集群数N/2;

        4)、另外锁超时是所有的锁时间相加,如果超时时间5ms,集群1已经5ms,则加锁失败;

        5)、3、4步失败的话,就会进行解锁操作。

      缺点:

        集群情况下,对某个redis master实例,写入myLock这种锁key的value,会异步复制给对应的master slave。当master宕机,主备切换,redis slave变成redis master,会导致客户端2来加锁的时候在新的客户端上完成加锁(加锁针对1台机器),客户端1也进行了加锁。 就会多个客户端对一个分布式锁进行加锁,产生脏数据。

    4、ZooKeeper分布式锁的实现原理

      多个客户端(线程)争抢一个zk分布式锁:

        1)、所以线程都会创建一个锁节点下的一个接一个的顺序节点,按照请求时间设置一个字段排序;

        2)、当访问到zk的锁节点时候,自己是第一顺序位,就加锁。 如果自己不是第一顺序位,就对上一个顺序位的节点加监听器;

        3)、只要监听到上一个节点释放了锁,自己就排序到前一个顺序位了。

      其实就是一个排队机制。

    参考:纯洁的微笑、石杉的架构笔记、java版web项目、架构师之路、springForAll社区等公众号。

  • 相关阅读:
    【OpenCV学习】安防监控可疑走动报警
    【OpenCV学习】OpenMP并行化实例
    【OpenCV学习】cvConvert的使用
    【OpenCV学习】Fuzzy Logic模糊逻辑边缘提取
    C# 委托系列(一)将方法作为方法的参数
    关于dev的Gridview控件的行数据的颜色控制,根据不同的值设置不同颜色
    将gridcontrol导出到excel
    DataGridView中将某行设置为当前可见区域第一行
    如何获得窗体上控件相对于屏幕的位置?
    dev 控件 lookupedit 设置选项值
  • 原文地址:https://www.cnblogs.com/AlmostWasteTime/p/10134993.html
Copyright © 2020-2023  润新知