复习——分布式锁


作者:空白

分布式锁原理图

分布式锁的架构原理图

alt

获取分布式锁:

1.多个进程抢占去获取锁中间件的flag变量

2.成功获取到flag的进程再执行之后的业务逻辑或数据访问逻辑。

3.无论是redis还是zookeeper,mysql都符合这样的架构图。

分布式锁实现方案大家族 alt

题集

分布式架构方案——分布式锁测试卷(一) alt

分布式架构方案——分布式锁测试卷(二) alt

分布式锁使用场景

  • 统计文章阅读量(一个用户一天多次只有一次参与计算)
  • 用户每天可以在app上签到领取平台金币,金币到达一定数量后可以换成人民币(超严格场景)

分布式锁知识要点

分布式锁要素

  • 分布式锁机制涉及对象:int类型变量 ,不同机器上服务中的线程 。
  • 分布式锁的高可用。
  • 复杂的业务情况下,还需要锁支持可重入特性。
  • 获取锁操作有两种特性:定量重试+超时失败(非阻塞锁)。
  • 阻塞锁实现和非阻塞锁实现,非阻塞锁又有直接失败和重试失败两种。

常见问题整理

  • 锁无法释放
  • 锁过期时间少于业务执行时间
  • 锁被其他线程释放

分布式锁场景及目的

  • 不同JVM(同一主机或不同主机)的线程共同访问一个数据,保证数据安全

分布式锁常见解决方案 (参考地址 三种实现分布式锁的方式

  • 数据库+唯一索引+插入/状态更新
  • 基于redis多种api实现
  • zookeeper实现分布式锁

常见场景:“分布式锁”是用来解决分布式应用中“并发冲突”的一种常用手段

  • 分析场景是否会有并发冲突。
  • 投票功能:一人一天只能投票一次的后端集群服务控制。
  • 并发请求,不论哪一条都必须要处理的场景(即:不允许丢数据) 比如:一个订单,客户正在前台修改地址,管理员在后台同时修改备注。地址和备注字段的修改,都必须正确更新,这二个请求同时到达的话,如果不借助db的事务,很容易造成行锁竞争,但用事务的话,db的性能显然比不上redis轻量。
  • 抢不到锁的请求,允许丢弃(即:忽略) 比如:一些不是很重要的场景,比如“监控数据持续上报”,某一篇文章的“已读/未读”标识位更新,对于同一个id,如果并发的请求同时到达,只要有一个请求处理成功,就算成功。

分布式锁的问题:

  • 获取锁的服务宕机,导致锁永远不是释放。

    • 给锁一个过期时间。
  • (因锁过期,误删除锁)A线程的锁过期了,但A未执行完,此时B获得了锁,A执行完的时候删除了B的锁。

    • 方案一: 为了避免这种情况,在del锁之前可以做一个判断,验证key对应的value是不是自己线程的ID.如果要考虑原子性问题,可以使用Lua脚本来实现,保证验证和删除的原子性。
    • 方案二:我们可以让获得锁的线程开启一个守护线程,用来给快要过期的锁加长超时时间。当系统A中的线程执行完任务,再显式关掉守护线程。
  • (主从数据不一致导致锁数据丢失)多节点部署场景(多主多从,一主一从),锁数据在主从之间不一致,未及时同步,从节点担任主节点后没有锁数据。

    • RedLock用来解决多节点部署的分布式锁如何安全获取问题。
    • 在redis分布式环境中,我们假设有N个Redis master.这些节点相互之间时独立的,不存在主从复制或者其他集群协调机制。我们确保将在N个实例上使用在Redis单实例下相同的方式获取和释放锁。
  • redlock,redisson分布式锁工作原理现: 在我们假设有5个Redis master节点。为了获取到锁,客户端应该执行以下操作:

    • 获取当前Unix时间,以毫秒为单位。
    • 依次尝试从5个实例,使用相同的key和具有唯一性的value获取锁。当向Redis请求获取锁时,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于锁的失效时间,是为了避免服务器端Redis已经挂掉,客户端还在一直等待响应结果。如果没有及时响应,客户端尽快去另一个Redis实例请求获取锁。
    • 客户端使用当前时间减去开始获取锁的时间,就得到获取锁使用的时间,当且仅当从大多数(N/2 + 1, 这里是3个节点)的Redis节点都取到锁,并且使用的时间小于锁失效的时间,锁才算获取成功。key的真实有效时间等于有效时间减去获取锁所使用的时间。
    • 如果因为某些原因,获取锁失败(没有在至少N/2 + 1个Redis实例上获取到锁),客户端应该在所有的Redis实例上进行解锁(即便是某些Redis实例根本没有加锁成功,防止某些节点获取到锁但是客户端没有得到响应而导致一段时间不能重新获取锁)
    • 注意: value一定要具有唯一性,防止误删锁,比如可以使用UUID+threadId
  • RedLock缺陷

    • 对于正确性严格要求的场景(比如订单), redLock也不能保证锁的正确性。
      • 解决方法:为锁增加一个token-fencing,获取锁的时候,还需要获取一个递增的token,在提交数据的时候,需要判断token的大小,如果token小于上一次提交的token,则提交被拒绝。 可以理解为这是一个乐观锁。(附言:都加版本号来控制了,还要分布式锁干啥)
    • RedLock是一个严重依赖系统时钟的分布式系统,如果某个Redis Master的系统时间发生了错误,造成了它持有的锁提前过期被释放。Client 1 在A,B,C, D, E五个节点中给,获取了A, B,C三个节点的锁,我们认为他持有了锁,这时由于系统B的时间比别的系统快,B就会优先释放锁,Client 2就可以从B,D,E三个节点中获取到锁,这样就造成了分布式系统中两个client同时持有锁。
扫码或搜索:前沿科技
发送 290992
即可立即永久解锁本站全部文章