动物园管理员实现分布式锁安全用法

  
      <李>背景李   <李> ConnectionLoss链接丢失李   <李> SessionExpired会话过期   <李>绕开动物园管理员代理进行状态通知李   <李>领导选举与zkNode断开李   <李>做好幂等李   <李>静态扩容,动态扩容李   
  

背景

  

分布式锁现在用的越来越多,通常用来协调多个并发任务。在一般的应用场景中存在一定的不安全用法,不安全用法会带来多个大师在并行执行、业务或数据可能存在重复计算带来的副作用,在没有拿到锁的情况下扮演者大师等诸如此类。

  

要想准确的拿到分布式锁,并且准确的捕获在分布式情况下锁的动态转移状态,需要处理网络变化带来的连锁反应。比如常见的会话过期,connectionLoss,在设置锁状态的时候我们如何保证准确拿到锁。

  

在设计任务的时候我们需要具有停止点的策略,这个策略是用来在感知到锁丢失后能够交付执行权的机制。但是是否需要这么严肃的处理这个问题还取决于业务场景,比如下游的任务已经做好幂等也无所谓重复计算。但是在有些情况下确实需要严肃精准控制。

  

ConnectionLoss链接丢失

  

先说第一个场景,connectionLoss事件,此事件表示提交的承诺有可能执行成功也有可能执行失败,成功是指在动物园管理员代理中执行成功但是返回的时候tcp断开了,导致未能拿到返回的状态。失败是指根本就没有提交到zookeper代理中链接就断开了。

  

所以在我们获取锁的时候需要做connectionLoss事件处理,我们看个例子。

  
 <代码>保护无效runForMaster () {
  
  logger.info(“师父:竞选主人。”);
  
  AsyncCallback。StringCallback createCallback=(rc、路径、ctx、名称)→{
  开关(KeeperException.Code.get (rc)) {
  案例CONNECTIONLOSS:
  checkMaster();//链接失效检查znode设置是否成功
  返回;
  案例好:
  isLeader=true;
  logger.info(“大师:我领导serverId:“+ serverId);
  addMasterWatcher();//监控znode大师
  this.takeLeadership();//执行领袖权利
  打破;
  案例NODEEXISTS:
  isLeader=false;
  字符串serverId=this.getMasterServerId ();
  this.takeBackup (serverId);
  打破;
  
  }
  };
  
  zk。创建(rootPath + "/大师”,serverId.getBytes (), ZooDefs.Ids.OPEN_ACL_UNSAFE,
  CreateMode。短暂、createCallback null);//创建主节点
  }/* *
  *检查主循环检查
  */私人空间checkMaster () {
  
  AsyncCallback。DataCallback masterCheckCallback=(rc、路径、ctx、[]的数据,统计)→{
  开关(KeeperException.Code.get (rc)) {
  案例CONNECTIONLOSS:
  checkMaster ();
  返回;
  案例九极管:
  runForMaster ();
  返回;
  默认值:{
  字符串serverId=this.getMasterServerId ();
  isLeader=serverId.equals (this.serverId);
  如果(BooleanUtils.isNotTrue (isLeader)) {
  this.takeBackup (serverId);
  其他}{
  this.takeLeadership ();
  }
  }
  
  返回;
  }
  };
  
  zk。getData (masterZnode、虚假、masterCheckCallback null);
  }
   
  

这里的主人表示具有执行权,只有成功拿到主人的角色才能履行主权利。

  

runForMaster方法一旦发现有connectionLoss就发起checkMaster进行检查,同时checkMaster方法中也进行connectinLoss检查,直到拿到明确的状态为止。在此时有可能有另外的节点获取到了主人的角色,那么当前节点就做好备份等待机会。

  

我们需要捕获管理员所有的状态变化,要知道大师什么时候失效做好申请准备,当自己是主人时候会话失效需要释放主权利。

  
 <代码>/* *
  *监控主znode做主/从切换
  */私人空间addMasterWatcher () {
  
  AsyncCallback。StatCallback addMasterWatcher=(rc、路径、ctx、统计)→{
  开关(KeeperException.Code.get (rc)) {
  案例CONNECTIONLOSS:
  addMasterWatcher ();
  打破;
  案例好:
  如果(stat==null) {
  runForMaster();//主已经不存在
  其他}{
  logger.info(“大师:观察者主znode好的。”);
  }
  打破;
  案例九极管:
  logger.info(“主:主znode删除。”);
  runForMaster ();
  打破;
  }
  };
  
  zk。存在(masterZnode MasterExistsWatcher addMasterWatcher, null);
  } 
  

通过饲养员观察家机制来进行状态监听,保持与网络,饲养员状态变化联动。

  

SessionExpired会话过期

  

我们在来看第二个问题,第一个问题是获取锁的时候如何保证一定可以准确拿到状态,这里状态是指掌握角色或者备份角色。

动物园管理员实现分布式锁安全用法