Abstract

数据中心的很多服务都有赖于基于分布式锁和消息队列原语的协调和同步操作。我们认为将这些系统当中的协调服务设计为可扩展的是一件非常重要的事。如果不恁能够扩展协调服务的功能,有可能到头来一直在用一个不好的协调算法,最后导致低性能。而添加了扩展性,则需要一些机制来约束扩展以能够作出合理的安全性和性能的保证。我们提出了一个方案,它允许我们以安全的方式,动态地引入和移除扩展。为了避免设计差的插件带来性能上的开销,它限制了扩展对资源的访问。最终的测试中,扩展版本的 ZooKeeper 和 DepSpace 都在分布式的队列中获得了一个数量级的性能提升 (17x for Zookeeper, 24x for DwpSpace),并且其依赖的协调核心能够保持很小的体积。

Introduction

现代的 Web-scale 服务很复杂,很难设计和维护。一部分复杂性来源于满足可扩展性和容错;另外一部分来源于使用极其复杂的分布式协议,它们出了名地难实现。于是协调服务就被提出并投入使用,以在对外给出更加简洁的接口的同时,提供同样的服务。

简而言之,协调服务提供了一个一致的、高可用的数据存储,拥有足够的同步能力以应对客户端进程对基本任务的执行,如互斥操作和领导选举,并且储存重要的系统配置。这样的客户端通常是在上百上千服务器集群上部署的服务进程。协调服务的两个特性解释了它们成功的原因:1、它们为更大的分布式系统提供了一个坚实可信的锚点(基础?),使用坚固的状态机复制协议实现来避免所有的单点错误,并且 2、它们的少而有限的接口,也叫做协调内核,能够以简单的 RPC 的形式被调用,就算不是分布式计算编程的专家,也能够凭直觉弄懂。

尽管简化了使用,有限的协调内核也有一个明显的缺点:受限在一组特定的原语之内。更加复杂的协调任务,比如一个分布式队列,必须被实现为一组多个 RPC 调用,在性能上非常吃亏。例如,因为 ZooKeeper 没有提供在数据节点当前值的基础上更新值的原语,这样的一个操作必须用一个读再根据情况写入来实现,导致在资源抢占较频繁的条件下的性能非常糟糕。这种缺陷是有限的协调内核天生就有的。一种办法是增加新的原语,然而这也就导致丢失了上面所说的有限接口的好处。

在这篇工作中,我们因此而采用了不同的办法:让协调服务变为可扩展的。因此,我们展示了一个模型,它允许客户端动态地、安全地扩展一个协调服务,通过一小段定制的代码在服务端原子地运行。另外,我们设计了一个沙盒来约束这些扩展不要降低或干碎整个系统的性能。