云计算设计模式(十三)——*选举模式

云计算设计模式(十三)——*选举模式


通过协调合作,在分布式应用程序的任务实例集合执行的操作,选举一个实例作为承担管理其他实例责任的领导者这个模式可以有助于确保任务实例不互相冲突导致争用共享资源与其他的任务实例正在执行工作无意中干扰

背景和问题


一个典型的云应用包括行动协调的方式很多任务这些任务都可以是实例运行相同的代码需要访问相同的资源,或者它们可能是可并行工作,以执行复杂计算的各个部分

任务实例可能时间自主运行,但它也可能是必要的,以协调实例的操作,以确保它们不发生冲突导致争用共享资源无意中妨碍工作,其他的任务实例正在执行例如
•在基于云的系统,该系统实现了横向扩展同一个任务的多个实例可以每个实例服务于不同的用户同时运行如果这些实例写入到共享资源,也可能是必要的,以协调它们的操作,以防止每个实例盲目地覆盖他人进行的更改。
•如果任务正在执行复杂的计算以并行单个元素,其结果将需要被聚合时,他们完成了。

由于任务实例都是同行,没有天生的领导者,能够充当协调员或聚合器。

解决方案


单个任务实例应选充当领导者,这种情况下应协调其他从属任务实例操作。如果所有的任务实例都运行相同的代码他们可能能够充当领导者因此选举过程必须谨慎管理,以防止两个或多个实例接管领导者的角色在同一时间

该系统必须选择的领导者提供了一个坚固的机构这种机制必须能够应付诸如网络中断进程故障事件。在许多解决方案中,下属的工作情况监控的领导者,通过某种类型的心跳机制通过轮询如果指定的领导者意外终止网络故障使得领导者不通下属的工作情况有必要为他们选出了新的*

有可用于选举的领导者之间的一组任务在分布式环境中,包括几个策略:
排名最低的实例或进程ID选择任务实例
竞速获得一个共享的分布式互斥第一个任务实例获取该互斥锁处于领先地位然而,系统必须保证,如果领导者终止变得与系统的其余部分断开,该互斥被释放,以允许另一个任务实例成为领导者。
•实施的共同*选举算法,如恶霸算法算法之一。这些算法相对简单的但也有一些更复杂的技术提供。这些算法假定每个候选参选具有唯一的ID并且,它们可以可靠的方式其他候选人进行通信

 

问题和注意事项


在决定如何实现这个模式时,请考虑以下几点
选出一个领导者的过程应该是弹性的瞬时和永久失效
必须能够检测到当领导失败,或变成不可用(可能是由于通讯故障这是需要这种检测速度将取决于系统。有些系统可能能够发挥作用一会儿没有一个领导者,在此期间造成*变得不可用瞬时故障可能已被排除其他情况下,可能有必要立即检测领袖失败并引发新的选举。
在实现自动缩放水平的系统中,如果系统背面关闭一些计算资源领导者可能被终止。
•使用一个共享的分布式互斥引入外部服务,提供互斥锁的可用性依赖。该服务可以构成一个点故障。如果此服务应该以任何理由变得不可用时,系统将无法选出一个领导者
•使用一个专用进程的领导者是一个比较简单的方法然而,如果该过程失败,可能有显著延迟重新启动,并且将得到的延迟可能影响其他进程的性能和响应时间,如果他们正在等待*来协调的动作
•实施*选举算法之一手动调整和优化代码的最大灵活性。


何时使用这个模式


使用此模式时,在分布式应用程序任务比如云托管解决方案需要认真协调,也没有天生的领导者

注意:

避免使领导者在系统中的瓶颈。领导者的目的是协调附属任务完成的工作,它不一定有机会参加这项工作本身尽管它应该是有能力这样做,如果任务没有当选*

这种模式可能不适合
如果有一个天生的领导者或专用的过程,可以随时充当领导者。例如有可能实现一个单进程,其协调该任务的实例。如果这个过程失败或变得不健康,系统可以将其关闭并重新启动它
•如果任务之间的协调,可以很容易地通过使用更轻便的机构来实现的。例如,如果几个任务实例仅仅需要对共享资源的访问协调一个最好的解决办法可能是使用乐观悲观锁来控制访问该资源。
如果一个第三方的解决方案是比较合适的例如,微软的Azure HDInsight服务基于Apache Hadoop的)使用所提供的ApacheZookeeper协调的map / reduce汇总任务和汇总数据服务它也可以安装并在Azure的虚拟机配置动物园管理员,并将其集成到自己的解决方案或使用可从微软开放技术动物园管理员预置的虚拟机映像欲了解更多信息,请参阅Apache的动物园管理员在微软的Azure微软开放技术的网站。

例子


列入可用于本指南的示例代码LeaderElection解决方案DistributedMutex项目展示了如何使用租赁Azure存储BLOB提供了一种机制,实现共享的分布式互斥此互斥锁可以用来选择Azure云服务的领导者之间的一组角色的实例第一个角色实例获得租约当选*并保持领先直至其租赁或直到它无法续租其他角色实例可以继续监视领导不再可用的情况下将BLOB租赁

注意:

一个BLOB租赁是一个blob排他写锁。单个BLOB可以是一整任何一个时间的问题。角色实例可以请求租约在指定的斑点而且将被授予租约,如果没有其他租赁在同一个斑点,是由这个或任何其他作用,比如举行否则将抛出一个异常
为了减少一个故障角色实例保留无限期租用的可能性指定了一辈子租约。当此期满后,租赁变为可用然而,当一个角色实例持有租赁可以请求租约到期并且将被授予租约的时间再延长角色实例可以不断重复这一过程,如果它希望保留租约
有关如何租用一个blob的详细信息,请参阅租赁斑点REST API在MSDN上



在该实例中BlobDistributedMutex类包含RunTaskWhenMutexAquired方法,使一个角色实例试图获得租约在指定的斑点团块名称,容器和储存的帐户的细节传递给构造一个BlobSettings对象被创建BlobDistributedMutex对象这个对象是包含在示例代码的简单结构)构造函数也接受一个任务,它引用角色实例应该运行,如果它成功收购租赁BLOB和当选*的代码。需要注意的是处理获得租约低层次细节中的代码名为BlobLeaseManager一个单独的辅助类实现

public class BlobDistributedMutex
{
  ...
  private readonly BlobSettings blobSettings;
  private readonly Func<CancellationToken, Task> taskToRunWhenLeaseAcquired;
  ...

  public BlobDistributedMutex(BlobSettings blobSettings, 
           Func<CancellationToken, Task> taskToRunWhenLeaseAquired)
  {
    this.blobSettings = blobSettings;
    this.taskToRunWhenLeaseAquired = taskToRunWhenLeaseAquired;
  }
  
  public async Task RunTaskWhenMutexAcquired(CancellationToken token)
  {
    var leaseManager = new BlobLeaseManager(blobSettings);
    await this.RunTaskWhenBlobLeaseAcquired(leaseManager, token);    
  } 
  ...


代码示例中RunTaskWhenMutexAquired上述方法调用以下代码示例来实际获得租赁所示的RunTaskWhenBlobLeaseAcquired方法RunTaskWhenBlobLeaseAcquired方法异步运行如果租赁成功获取角色实例已经当选的领导者taskToRunWhenLeaseAcquired委托的目的是为了执行协调其它角色实例的工作。如果未取得租赁另一个角色实例已当选为*和当前角色实例仍然是一个下属注意,TryAcquireLeaseOrWait方法是使用BlobLeaseManager对象获取租赁一个辅助方法

 

 ...
  private async Task RunTaskWhenBlobLeaseAcquired(
    BlobLeaseManager leaseManager, CancellationToken token)
  {
    while (!token.IsCancellationRequested)
    {
      // Try to acquire the blob lease. 
      // Otherwise wait for a short time before trying again.
      string leaseId = await this.TryAquireLeaseOrWait(leaseManager, token);

      if (!string.IsNullOrEmpty(leaseId))
      {
        // Create a new linked cancellation token source so that if either the 
        // original token is cancelled or the lease cannot be renewed, the
        // leader task can be cancelled.
        using (var leaseCts = 
          CancellationTokenSource.CreateLinkedTokenSource(new[] { token }))
        {
          // Run the leader task.
          var leaderTask = this.taskToRunWhenLeaseAquired.Invoke(leaseCts.Token);          
          ...
        }
      }
    }
  }
  ...


 

由领导开始的任务还异步执行。虽然这个任务正在运行,下面的代码示例所示的RunTaskWhenBlobLeaseAquired方法周期性地尝试续订租约。这个动作有助于确保该角色实例保持领先。在简单解决方案中,续订请求之间的延迟小于对租赁期限,以防止另一角色实例当选的*指定的时间。如果更新失败,以任何理由,任务被取消。如果租用未能被更新或任务被取消(可能为角色实例关停的结果),租赁被释放。在这一点上,这个或另一个角色实例可能被选为领导者。下面的代码提取物显示出此过程的一部分。

...
  private async Task RunTaskWhenBlobLeaseAcquired(
    BlobLeaseManager leaseManager, CancellationToken token)
  {
    while (...)
    {
      ...
      if (...)
      {
        ...
        using (var leaseCts = ...)
        {
          ...
          // Keep renewing the lease in regular intervals. 
          // If the lease cannot be renewed, then the task completes.
          var renewLeaseTask = 
            this.KeepRenewingLease(leaseManager, leaseId, leaseCts.Token);

          // When any task completes (either the leader task itself or when it could
          // not renew the lease) then cancel the other task.
          await CancelAllWhenAnyCompletes(leaderTask, renewLeaseTask, leaseCts);
        }
      }
    }
  }
  ...
}


 

KeepRenewingLease方法是使用BlobLeaseManager对象续租另一个helper方法CancelAllWhenAnyCompletes方法取消指定为前两个参数的任务。

图1示出BlobDistributedMutex的功能。

云计算设计模式(十三)——*选举模式

图1 - 使用BlobDistributedMutex选出一个领导者和运行协调操作的任务


下面的代码示例显示了如何使用BlobDistributedMutex辅助角色此代码获取租赁一个名为MyLeaderCoordinatorTask开发仓储租赁容器中的blob并指定MyLeaderCoordinatorTask方法定义的代码应该运行,如果角色实例当选*

var settings = new BlobSettings(CloudStorageAccount.DevelopmentStorageAccount, 
  "leases", "MyLeaderCoordinatorTask");
var cts = new CancellationTokenSource();
var mutex = new BlobDistributedMutex(settings, MyLeaderCoordinatorTask);
mutex.RunTaskWhenMutexAcquired(this.cts.Token);
...

// Method that runs if the role instance is elected the leader
private static async Task MyLeaderCoordinatorTask(CancellationToken token)
{
  ...
}


 

请注意有关样品溶液中的以下几点
BLOB一个潜在的单点故障。如果Blob服务不可用,的blob人迹罕至,领导者将无法续租,并没有其他的作用,比如能够获得租约这种情况下,没有作用,例如将能够充当领导者。然而,的blob服务被设计为弹性的,所述的blob的服务,以便彻底失败被认为是极不可能的
如果领导者摊位正在执行的任务,领导者可能会继续续租,防止任何其他角色实例获得租约,并接管领导作用,以协调任务在现实世界中,领导者健康应该频繁地进行检查。
•在选举过程具有不确定性你不能做任何假设哪个角色实例得到的blob租约,成为领导者。
不应使用任何其他目的用作的blob租赁目标的blob如果一个角色实例尝试将数据存储在的blob,该数据不能被访问,除非该角色实例是领导者持有的blob租约。

本文翻译自MSDN:http://msdn.microsoft.com/en-us/library/dn568104.aspx

 

 

上一篇:云计算设计模式(五)——计算资源整合模式


下一篇:JavaEE Hibernate使用