分布式锁
分布式锁 基于数据库 乐观锁(数据更新之前先查状态,起冲突就更新失败) 悲观锁(for update,会占有,不利于并发) 获取锁的前提:结果集中的数据没有使用排他锁或共享锁时,才能获取锁,否则将会阻塞。 需要注意的是, FOR UPDATE 生效需要同时满足两个条件时才生效: 数据库的引擎为 innoDB 操作位于事务块中(BEGIN/COMMIT) 实现: 表加唯一索引 加锁:insert语句,报错证明加锁失败 解锁:delete 实现简单 数据库开销大、性能不高 没有自动超时机制,有死锁风险 基于Redis缓存 加锁:SET k v EX 300 NX 解锁:DELETE 可能会删除不是这个线程拥有的锁 解决:验证value(写value的时候也得保证唯一) 如果这个master节点由于某些原因发生了主从切换,那么就会出现锁丢失的情况: 在Redis的master节点上拿到了锁; 但是这个加锁的key还没有同步到slave节点; master故障,发生故障转移,slave节点升级为master节点; 导致锁丢失。 基于Zookeper 获得锁和等待 创建一个持久结点 C1获得锁:从持久结点创建临时结点Lock1。C1查找所有临时结点并排序,是最前的 一个就获得锁 C2获取锁,创建临时结点Lock2。查找所有临时结点并排序,发现不是最前,创建watch观察最近的Lock1 C3获取锁,创建临时结点观察最近的Lock2 形成等待队列 删除锁 C1调用删除Lock1 的指令(临时结点在C1断开连接时也会自动删除Lock1) C2因为watch着Lock1,删除后立即得到通知 再次查询所有临时结点,并排序,发现自己是最小的,获得锁 acquire方法用户获取锁,release方法用于释放锁。 性能不高,因为要创建临时结点 对于客户端Client断开的情况,Curator客户端支持多种重试策略。多次重试之后还不行的话才会删除临时节点。