• 分布式锁


    1.什么是分布式锁

      分布式锁是控制分布式系统之间访问共享资源的一种方式。

      在分布式系统中,常常需要协调他们的动作,如果不同的系统/服务/应用程序访问了同一个或一组资源,

      那么在访问这些资源的时候,需要使用互斥防止彼此产生干扰来保证数据一致性,那么就需要使用分布式锁。

      

      下图是分布式的一种场景,但是没有体现临界资源的概念,本人比较懒,直接摘抄原图。

      下面JVM1,JVM2,JVm3实际指向同一个临界资源(举例:数据库),三个进程需要更新同一份数据,那么需要控制并发问题

      

       

    2.分布式锁的特性

      互斥:一个临界资源同一时间只能被一个线程执行

      可重入:已经获取锁的人(尚未释放),可多次重新获取

      失效机制:锁需要有一定的有效期,避免因为获取到锁的服务进程奔溃导致锁无法释放

      非阻塞:获取锁成功或者失败,都立马返回,不阻塞(在有些场景下,获取不到锁的人,就不需要干活了,所以不应该阻塞)

      高可用、高性能的获取锁和释放锁

    3.分布式锁的实现方案列举

      

      

     4.基于数据库的实现

      悲观锁:直接使用某个临界资源表,获取锁的时候调用select ... for update来获取锁,其它竞争服务获取不到锁会阻塞等待,效果不好

      乐观锁:新建临界资源表,每条锁对应一个记录,每条记录有一个版本号,更新数据时判断版本号是否和自己预期一致

    5.基于zookeeper的实现

     基本思想:各服务进程在某个锁下创建临时、有序节点, 同时注册watch监听事件

      节点名最小的服务获取到锁

      使用完锁时删除节点,后面的节点因为注册了watch监听事件,所以可以收到通知,下一个节点获取到锁

      如果使用锁的过程中,进程崩溃,由于使用的是临时节点,zookeeper感知到进程退出后,会删除临时节点,后面的节点会收到通知

      

     6.基于redis的实现

      使用setnx竞争设置一个key,拿到key的人表示获取到了锁(setnx就是没有则设置)(互斥)

      获取锁的同时需要增加超时时间设置,避免自己奔溃后,锁无法释放(这两步需要是原子操作)(失效机制)

      使用锁的过程中,需要进行锁的保活,因为redis中key的超时时间是固定的,但是执行时间不固定的,避免key过期,其它进程同时获取到锁

      释放锁的时候,需要检查这个key对应的值是否是自己,避免因为自己的锁失效(下一个人已经获取到锁),导致后面连锁反应,全部人都获取到锁

    7.Redlock(红锁)

      redlock是集群模式的redis分布式锁,它基于集群中n个的redis节点进行加锁。

      主要是因为redis集群的数据一致性实时性相对较差,在一个节点上写成功的数据,其它节点不一定能看到,所以集群模式下,不能单独的锁一台redis实例。 

      备注:zookeeper不需要,是因为zk是基于CP原则实现的,而且是顺序节点,那么客户端要么看不到,要么看到的是正确数据

      1.客户端获取当前时间,以毫秒为单位

      2.客户端尝试获取n个节点的锁,每个节点获取锁的方式同上面单机redis

      3.客户端计算计算在获取锁的过程中总共花费时间,时间小于超时时间且获得了半数以上的锁,则获取锁成功

      4.更新锁的超时时间(预定义超时时间-获取锁的时间)

      5.如果获取锁失败,则删除所有的锁

    参考文档:

      https://www.jianshu.com/p/a1ebab8ce78a

      https://www.cnblogs.com/ldws/p/12155003.html

      

  • 相关阅读:
    iOS--异步下载
    linux搭建ftp服务器
    hexo常用命令
    Markdown入门
    Markdown 语法和 MWeb 写作使用说明
    vi/vim
    微信聊天机器人
    .vimrc
    配置双机
    python学习笔记(一)
  • 原文地址:https://www.cnblogs.com/gc65/p/12774218.html
Copyright © 2020-2023  润新知