zoukankan      html  css  js  c++  java
  • 分布式锁方案和缺陷

    分布式锁使用场景

    • 解决业务层幂等性,防止双次点击(譬如更新接口)
    • 解决 MQ 消费端多端接受同一消息时保证只有一端处理消息
    • 使用 schedule 执行定时任务时,多实例部署时只有一台实例执行任务

    Redis

    特点

    • 单线程串行处理
    • 获取锁性能特别好
    • setnx 不存在则设置成功否则失败
    • 没有心跳机制,需要设置失效时间
    • CAP 中的 AP 模型,因为用的是 gossip 协议,所以不是强一致性

    多个业务获取锁场景

    锁失效时间设置问题

    锁定了10s后过期,但业务执行了30s(可能碰到fullgc,死循环等场景)。

    主从切换问题

    业务1从主获取锁,此时主挂机了,从晋升为主,恰好此时从未同步这个锁的值 。

    Zookeeper

    特点

    • 有序节点,按排序命名节点
    • 临时节点,客户端断连后自动消失
    • 事件监听,节点下发生更新时会有事件通知
    • ZAB 协议,强一致,属于 CP 模型
    • zk 集群变大后,性能持续下降

    多个业务获取锁场景

    客户端挂掉或假死

    客户端断连会把临时节点删除,锁也就随着释放。另一个业务即可获取锁。
    但其实客户端没挂,只是心跳维持间断了。原因有好多,譬如fullgc,网络问题(redis碰到网络问题最多获取锁失败)等。

    Etcd

    特点

    • 如果存在 Key 的话就不能写入,也就意味着不能获取到锁,如果集群中,可以写入 Key,就意味着获取得到锁。
    • Raft 保证了集群的一致性,强一致性,并且数据是可以进行持久化
    • 没有心跳机制,需要设置失效时间

    多个业务获取锁场景

    锁失效时间设置问题

    锁定了10s后过期,但业务执行了30s(可能碰到fullgc,死循环等场景)。

    使用失效时间的锁时间续租问题

    在获取到锁的业务线程,可以开启一个子线程去维护和轮训这把锁的有效时间,并定时的对这把锁进行续租。
    假设业务线程获取到一把锁,锁的 Expire 时间为 10s,业务线程会开启一个子线程通过轮训的方式每 2 秒钟去把这把锁进行续租,每次都将锁的 Expire 还原到 10s。

    存在的问题

    • 业务死循环
    • 业务 fullgc

    这些问题都会导致续租线程无法执行,从而导致锁提前失效。

  • 相关阅读:
    [k8s]kube-dns/dashboard排错历险记(含sa加载用法/集群搭建)
    禁用nginx的access日志
    redis info 各信息意义
    使用JProfiler进行内存分析
    lr11 BUG?Failed to send data by channels
    loadrunner 怎么能得到返回的http状态?
    SQL SERVER查看当前连接情况
    总结: Struts2 + Spring 的线程安全问题
    转发:maven打包时始终出现以下提示:-source 1.3 中不支持泛型(请使用 -source 5 或更高版本以启用泛型)
    SQL Server 索引结构及其使用(一)
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/11076457.html
Copyright © 2011-2022 走看看