zoukankan      html  css  js  c++  java
  • 分布式锁的各种实现

    locker

    分布式锁简介

    分布式锁目前实现大部分方式

    • 使用mysql
    • 使用redis
    • 使用zookeeper

    基于此,成熟的案例有比如redisson 这种官方比较推荐的方案,为了深入研究,准备在这个项目中复现这3种形式的锁

    锁的用途

    分布式锁主要可以独立于服务之外,主要的目的是在集群中保证同一时刻只能由锁的持有者对资源处理,释放锁的时候需要考虑到重入对资源的影响,串行化实现中,该项目使用了spring-retry的相关功能,将多个请求共同编排,
    实现全局的锁需要依赖一个第三方系统,此系统需要满足高可用、一致性比较强同时能应付高并发的请求。

    锁的不同实现方式

    该项目中所有的锁实现都放入了统一枚举,目前是采用的非公平锁来实现串行化执行的目的。

    me.fulln.lock.enums.LockEnum
    

    数据库锁

    • 非重入锁

    数据库非重入锁,依赖于数据库主键唯一冲突,在多个请求过来的时候,让最先访问到的请求,直接插入值来拿到锁,其他的则不断重试,直到失败,如果需要释放锁的话,直接将该锁逻辑删除即可

    • 可重入锁

    数据库可重入锁,需要在表新增一个标识,来区分是本身线程的重试还是其他线程的重试,只有允许该标识下的请求进入,并成功获取锁,多次进入时,会在次数上+1,
    释放锁的时候,需要判断该锁的次数是否完全达到释放的次数,每次释放将该锁的次数-1,直到0

    整体来说mysql数据库来做分布式锁是比较少的,大量时间耗费在数据库连接和数据传输上了,整体感还是比较重,而且mysql使用主键冲突来判断是否获取成功,实现的不算优雅,而且在集群下,由于主从同步的的时间差,容易出现误判的情况

    redis锁

    redis锁主要是有setnx 可进行唯一key的设置和获取,redis的setnx是redis的一个原子操作,如果key存在则set失败,如果不存在则set成功

    目前大部分分布式锁的实现都是由redis进行实现的,其实现简单,吞吐量不低,但是在集群模式下,主从复制,会遇见master锁成功后节点下线,未同步锁到其他节点,导致slave节点又一次锁成功,从而产生问题

    重试获取的在redission中也有很好的实践

    zookeeper锁

    zk锁是通过往zk中最先写入key节点,发现自己创建的节点是最小的节点,就认为这个客户端获取到了锁.其他的客户端再进行写入的时候,发现key已经存在或者在自己创建的节点的children不是最小的,就进行等待,直到下次锁被释放的时候,再去获取锁.

    zk实现的锁有个问题在于分布式锁会有羊群效应,即其他所有客户端在判断自己创建的节点是不是最小的时候,大部分都算出来不是最小的.大部分客户端都获取到了和自己不相干的通知,在集群下,对service的性能影响很大,并且如果一旦同一时间有多个节点的客户端断开连接,这个时候,服务器就会像其余客户端发送大量的事件通知,也是属于比较重的一种实现

    ps: 最好使用curator 来实现zk客户端连接

    项目地址

    https://github.com/fulln/locks

  • 相关阅读:
    windowssdk编程从简单的对话框开始
    面向扣扣编程知识一
    循序渐进DLL编程(二)
    西方经济学导论
    循序渐进DLL编程(五)
    HLSL Effect的vertex shader和pixel shader的参数传递
    Directx11 HelloWorld之与Directx9的比较
    Directx11 HelloWorld之简单三角形绘制
    正式开始记录自己学习历程
    坐标系的转换
  • 原文地址:https://www.cnblogs.com/wzqshb/p/14856569.html
Copyright © 2011-2022 走看看