-
<李>背景李>
<李> 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会话过期
我们在来看第二个问题,第一个问题是获取锁的时候如何保证一定可以准确拿到状态,这里状态是指掌握角色或者备份角色。