分布式技术原理笔记(二)分布式体系结构

第一章 集中式体系结构

集中式结构就是,由一台或多台服务器组成中央服务器,系统内的所有数据都存储在中央服务器中,系统内所有的业务也均先由中央服务器处理。多个节点服务器与中央服务器连接,并将自己的信息汇报给中央服务器,由中央服务器统一进行资源和任务调度:中央服务器根据这些信息,将任务下达给节点服务器;节点服务器执行任务,并将结果反馈给中央服务器。

集中式结构最大的特点,就是部署结构简单。这是因为,集中式系统的中央服务器往往是多个具有较强计算能力和存储能力的计算机,为此中央服务器进行统一管理和调度任务时,无需考虑对任务的多节点部署,而节点服务器之间无需通信和协作,只要与中央服务器通信协作即可,具体示意图如下所示:

以 Google Borg、Kubernetes 和 Apache Mesos 三个经典的集群管理系统为例,深入学习集中式结构的原理。

1.1 Google Borg

Borg 是 Google 内部使用的集群管理系统,采用了典型的集中式结构,负责提交、调度、开始、重启和管理 Google 运行在其上的所有应用。在 Borg 中,一个集群称为一个 Cell,每个 Cell 里面有一个 Leader,称为 BorgMaster,即为中央服务器;其他服务器为节点服务器从服务器,被称为 Borglet

BorgMaster由两个进程组成,一个是 Borgmaster 主进程,一个是独立的 scheduler 进程

  • 主进程处理客户端的 RPC 请求,比如任务的执行状态更新或者查询等;同时,管理系统中所有实体的状态(比如,服务器、任务等),并负责和 Borglet 通信
  • scheduler 进程负责任务调度,通过任务对资源的需求以及当前 Borglet 所在服务器的资源情况进行匹配,为任务寻找一个合适的节点服务器执行。

Borglet是运行在每个节点机器的一个 agent,负责任务的拉起、停止、重启等,并管理和收集本服务器资源,将任务的状态、服务器状态等信息上报给 BorgMaster。

而 BorgMaster 会周期性地轮询每个 Borglet,以获取节点服务器的状态和资源信息等。

Borg 的整体架构示意图如下所示:

Borg论文: https://storage.googleapis.com/pub-tools-public-publication-data/pdf/43438.pdf

Borg 的主要用户是 Google 的开发者以及运行 Google 应用和服务的系统管理员(网站可靠性工程师,简称 SRE)。用户以 Job 的形式向 Borg 提交工作,每个 Job 由运行一个或多个运行相同程序的 Task 组成。每个 Job 运行在一个 Borg Cell 中,并将一组机器当作一个单元进行管理。

Borg 可以运行各种各样的任务,这些任务主要分为两类:

  • 第一类是长服务,即长时间运行不停止的服务,并且要求能够处理短暂的、延迟敏感的请求(延迟要求在几微秒到几百毫秒之间)。这些服务主要用于面向终端用户的服务(比如 Gmail、Google Docs、Web 搜索),以及内部的一些基础设施服务(比BigTable)。
  • 第二类是批处理任务。通常需要几秒到几天的时间来完成的批处理 Job,这些 Job 对短时间的性能波动并不是非常敏感。

这些负载通常在 Cell 之间混合分布,每个 Cell 随着主要租户以及时间的不同会运行各种不同的应用:批处理类型的 Job 来了又走,而许多面向终端用户的 Job 又期望一个能长时间使用的模式。

对于这些不同的服务,要求 Borg 能很好地处理所有的情况。

Borg 主要有三大优点:

  • 开发者只需关注应用,不需要关注底层资源管理。它隐藏了资源管理以及错误处理,因此用户能集中精力开发应用。
  • 高可靠性和可用性,支持多种应用。
  • 支持上千级服务器的管理和运行。

Borg 并不是第一个解决这些问题的系统,但却是少数能在这么大规模处理这些问题的同时,还能实现这样的弹性和完整性的系统之一。

1.2 Kubernetes

Kubernetes 是 Google 开源的容器集群管理系统,是 Borg 的一个开源版本。Kubernetes 是用于自动部署、扩展和管理容器化应用程序的开源系统。其核心是,在集群的节点上运行容器化应用,可以进行自动化容器操作,包括部署、调度和在节点间弹性伸缩等。

Kubernetes 也是典型的集中式结构,一个 Kubernetes 集群,主要由 Master 节点和 Worker 节点组成,以及客户端命令行工具 kubectl 和其他附加项。

Master 节点运行在中心服务器上,Master 节点由 API Server、Scheduler、Cluster State Store 和 Control Manger Server 组成,负责对集群进行调度管理。

  • API Server:是所有 REST 命令的入口,负责处理 REST 的操作,确保它们生效,并执行相关业务逻辑。
  • Scheduler:根据容器需要的资源以及当前 Worker 节点所在节点服务器的资源信息,自动为容器选择合适的节点服务器。
  • Cluster State Store:集群状态存储,默认采用 etcd,etcd 是一个分布式 key-value 存储,主要用来做共享配置和服务发现。
  • Control Manager:负责整个集群的编排管理。它监视群集中节点的离开和加入,将群集的当前状态与 etcd 中存储的所需状态进行核对。比方说,当某个节点发生故障,它会在其它节点上增加新的 Pod 以匹配所需的副本数。

REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

Etcd 是一个分布式的,依赖key-value存储的,最重要的分布式数据存储系统。

Worker 节点作为真正的工作节点,运行在从节点服务器,包括 kubelet 和 kube-proxy 核心组件,负责运行业务应用的容器。

  • kubelet:用于通过命令行与 API Server 进行交互,根据接收到的请求对 Worker 节点进行操作。也就是说,通过与 API Server 进行通信,接收 Master 节点根据调度策略发出的请求或命令,在 Worker 节点上管控容器(Pod),并管控容器的运行状态(比如,重新启动出现故障的 Pod)等。Pod 是 Kubernetes 的最小工作单元,每个 Pod 包含一个或多个容器。
  • kube-proxy:负责为容器(Pod)创建网络代理 / 负载平衡服务,从 API Server 获取所有 Server 信息,并根据 Server 信息创建代理服务,这种代理服务称之为 Service。Kube-proxy 主要负责管理 Service 的访问入口,即实现集群内的 Pod 客户端访问 Service,或者是集群外访问 Service,具有相同服务的一组 Pod 可抽象为一个 Service。每个 Service 都有一个虚拟 IP 地址(VIP)和端口号供客户端访问。

Kubernetes 架构示意图如下所示:

Kube DNS 负责为整个集群提供 DNS 服务;CNI 是 Container Network Interface 的一个标准的通用接口,用于连接容器管理系统和网络插件。与 Borg 不同的是,Kubernetes 主要是一个容器编排引擎,不仅支持 Docker,还支持 Rocket(另一种容器技术)。

在容器管理方面,Kubernetes 有很多优势。

  • 自动化容器的部署和复制。Kubernetes 执行容器编排,因此不必人工编写这些任务的脚本。将容器组织为组,弹性伸缩。Kubernetes 引入 Pod 机制,Pod 代表着能够作为单一应用程序加以控制的一组容器集合。通过 Pod 机制,Kubernetes 实现了多个容器的协作,能够有效避免将太多功能集中到单一容器镜像这样的错误实践中。此外,软件可以向外扩展跨越多个 Pods 实现初步部署,且相关部署可随时进行规模伸缩。
  • 容器间负载均衡。Services 用于将具备类似功能的多个 Pod 整合为一组,可轻松进行配置以实现其可发现性、可观察性、横向扩展以及负载均衡。
  • 易于版本控制与滚动更新。Kubernetes 采取“滚动方式”实现编排,且可跨越部署范围内的全部 Pod。这些滚动更新可进行编排,并以预定义方式配合当前可能尚不可用的 Pods 数量,以及暂时存在的闲置 Pods 数量。Kubernetes 利用新的应用程序镜像版本对已部署 Pods 进行更新,并在发现当前版本存在不稳定问题时回滚至早期部署版本。

1.3 Mesos

Apache 旗下的开源分布式资源管理框架 Mesos 被称为是分布式系统的内核,最初由加州大学伯克利分校的 AMPLab 开发,后在 Twitter 得到广泛使用。

Mesos 的开发受到了 Borg 系统的启发,也是采用的典型的集中式架构。Mesos 与 Borg 不同之处在于,Borg 的 Master 直接对接用户应用,也就是说用户可以向 Borg 的 Master 直接请求任务。但 Mesos 不可以,Mesos 只负责底层资源的管理和分配,并不涉及存储、 任务调度等功能,因此 Mesos Master 对接的是 Spark、Hadoop、Marathon 等框架,用户的任务需要提交到这些框架上。也正因为此,Mesos 的任务调度框架是双层结构

在 Mesos 中,一个集群包括 Mesos Master 和多个 Mesos Agent。其中,Mesos Master 运行在中央服务器,Mesos Agent 运行在节点服务器上。

  • Mesos Master 负责收集和管理所有 Agent 所在服务器的资源和状态,并且对接 Spark、Hadoop 等框架,将集群中服务器的资源信息告知给这些框架,以便这些框架进行任务资源匹配和调度。
  • Mesos Agent 负责任务的拉起、停止、重启等,并负责收集所在服务器的资源 (比如 CPU、内存等) 信息和状态,上报给 Mesos Master。

Mesos Master 通常采用一主两备的方式,以方便故障处理和恢复。而 Mesos Master 的选主策略,采用的是 ZAB 算法

Mesos 架构示意图如下所示:

 如上所述,Mesos 对接的是框架,并且可以同时对接多个框架。

Mesos具有如下优势:

  • 效率。Mesos 对物理资源进行了逻辑抽象,在应用层而不是物理层分配资源,通过容器而不是虚拟机(VM)分配任务。因为应用程序的调度器知道如何最有效地利用资源,所以在应用层分配资源能够为每个应用程序的特殊需求做考量 ; 而通过容器分配任务则能更好地进行“装箱”。
  • 可扩展性。Mesos 可扩展设计的关键是两级调度架构,其中 Framework 进行任务调度,Mesos Master 进行资源分配。由于 Master 不必知道每种类型的应用程序背后复杂的调度逻辑,不必为每个任务做调度,因此可以用非常轻量级的代码实现,更易于扩展集群规模。
  • 模块化。每接入一种新的框架,Master 无需增加新的代码,并且 Agent 模块可以复用,为此开发者可以专注于应用和框架的选择。这,就使得 Mesos 可以支持多种框架,适应不同的应用场景。

随着分布式应用程序和微服务的流行,越来越多的用户正在寻找一种技术,来帮助他们管理这些复杂的应用程序。而 Mesos 为数据中心带来的这些好处,就使得越来越多的人关注 Mesos 及其相关项目。

Mesos 是如何支持容器部署的?

目前,容器技术十分热门,解决了服务打包发布、资源隔离的问题。我们知道,Kubernetes 的设计主要针对的就是容器,那么 Mesos 又是如何支持容器部署呢?Mesos 本身只负责资源管理,不负责任务调度。但 Mesos 可以对接不同的框架,Mesos+Marathon 可以支持容器调度和部署。Marathon 支持容器的调度,将容器部署请求发给 Mesos Master,Mesos Master 再将请求转发给 Mesos Agent,Mesos Agent 的执行器会将容器拉起。目前,Mesos+Marathon 支持的容器,主要包括 Docker 和 cgroups。

1.4 总结

在集中式架构中,Master 如何判断 Slave 是否存活呢?

  • Slave定时向Master汇报自己还活着,定时心跳包
  • Master定时询问Slave是否还活着,定时心跳包
  • Master与Slave之间建立TCP长链接

3 种集群管理系统的对比

第二章 非集中式体系结构

在非集中式结构中,服务的执行和数据的存储被分散到不同的服务器集群,服务器集群间通过消息传递进行通信协调。也就是说,在非集中式结构中,没有中央服务器和节点服务器之分,所有的服务器地位都是平等(对等)的。这样一来,相比于集中式结构,非集中式结构就降低了某一个或者某一簇计算机集群的压力,在解决了单点瓶颈和单点故障问题的同时,还提升了系统的并发度,比较适合大规模集群的管理。

所以近几年来,Google、 Amazon、Facebook、阿里巴巴、腾讯等互联网公司在一些业务中也相继采用了非集中式结构。

接下来,将介绍 3 种典型的非集中式架构系统,包括 Akka 集群、Redis 集群和 Cassandra 集群。

2.1 Akka 集群

在介绍 Akka 集群的结构之前,我带你了解一下什么是 Akka 框架吧。Akka 是一个开发库和运行环境,用于构建可扩展的、弹性的、快速响应的应用程序。Akka 框架是基于 Actor 模型实现的,Actor 模型是一个封装了状态和行为的对象,它接收消息并基于该消息执行计算。Actor 之间通信的唯一机制就是消息传递,每个 Actor 都有自己的 MailBox。

比如,在分布式系统中,一个服务器或一个节点可以视为一个 Actor,Actor 与 Actor 之间采用 mail 进行通信,如下图所示:

可以看到,Actor 发送的 Mail 消息会存储在接收方的 MailBox 中。默认情况下,接收方按照 mail 到达的先后顺序,从 MailBox 中提取 mail 消息,并进行相应的计算处理。

显然,Actor 模型采用异步消息调用机制,具有非阻塞、高性能等特点,可以用于处理并发问题。Akka 集群充分利用了 Actor 模型的优势,提供了一个非集中式架构的集群管理模块,用来构建可扩展的、弹性的分布式应用程序。

Akka 集群负责 Actor 模型底层的节点管理,包括故障检测、节点加入 / 退出集群等。也就是说,Akka 集群为 Actor 模型提供了一个可容错、去中心化的节点集群管理系统,来保证 Actor 的运行和 Actor 之间的通信。

Akka 集群是一个完全去中心化的分布式集群管理系统。一个集群由多个节点组成,每个节点都可以进行数据处理和任务执行,节点之间均可进行通信。节点有 Leader 节点和非 Leader 节点之分。与非 Leader 节点相比,Leader 节点只是增加了负责节点的加入和移除集群的功能,所以并不会影响非集中式结构中节点的平等关系。

Akka 集群的两个重点是数据传输集群组建及管理

首先,我们看一下数据传输。在 Akka 集群中,节点是对等的,也就是说每个节点是可以并发处理的,因此必然存在数据传输和一致性的问题。

比如,我们要针对数据进行操作,将 X=1 修改为 X=2。现在集群中节点 1 进行了修改使得 X=2,但其他节点上还是 X=1,因此节点 1 需要将 X=2 的消息告知其他节点,以保证最终集群中所有节点上均为 X=2。其实,这个问题就是分布式共识问题

布式共识是在多个节点均可独自操作或记录的情况下,使得所有节点针对某个状态达成一致的过程。

Akka 集群主要采用的是谁的时间戳最新(也就是数据最新),就以谁为准的原则。在这里我要重点与你讲述的是,如何将 X=2 这个消息传输给集群中的每个节点。

Akka 集群采用了 Gossip 协议,该协议是最终一致性协议。它的原理是每个节点周期性地从自己维护的集群节点列表中,随机选择 k 个节点,将自己存储的数据信息发给这 k 个节点,接收到该信息的节点采用前面讲的共识原则,对收到的数据和本地数据进行合并,这样迭代几个周期后,集群中所有节点上的数据信息就一致了。

来看一下集群组建及管理。下图展示了 Akka 集群的创建过程。在创建集群时,节点被分为三种类型,即:

  • 种子节点。使用静态配置文件方式或者系统运行时指定方式,可以生成种子节点;种子节点是普通节点加入集群的联系点,可以自动接收新加入集群的节点的信息。
  • 首种子节点。首种子节点是配置文件中的第一个种子节点,其功能是集群第一次启动时,首种子节点启动起来,集群才能组建成功,保证集群第一次创建时只有一个集群。如下图 A 节点,就是 Akka 集群的首种子节点。
  • 普通节点。可以向种子节点或集群中的任意节点发送 Join 消息,请求加入集群。如下图的 B 和 C 节点,通过向 A 节点发送 Join 消息,从而加入到 Akka 集群。

Akka 集群的每个节点启动后,读取配置文件获取种子节点列表,然后开始组建集群:

  • 如果本节点为首种子节点,则把自己加入到集群列表中,即以自己为中心构建集群;
  • 如果本节点为种子节点,则向首种子节点请求加入集群,当首种子节点回复同意消息后,可以加入集群,否则不可加入集群;
  • 如果本节点为普通节点,则可以向任一种子节点(包括首种子节点)请求加入集群,收到同意后,则加入集群,否则不可加入集群。

加入首种子节点或种子节点的节点信息,会通过 Gossip 协议的传播方式传播给当前已加入的所有节点,以完成集群组建。当集群组建完成后,就不存在种子节点与普通节点之分了,每个节点均可执行 Actor 应用程序。

Akka 集群可以构建可扩展的、弹性的分布式应用程序,因此在 JVM 中应用了 Akka 框架,从而实现并发编程。目前,豌豆荚、蘑菇街等公司采用了 Akka 集群。

Akka 集群是一个完全去中心化的集群管理系统,当集群组建完成后,每个节点均可执行 Actor 应用程序,因此支持并发操作。但,这个并发操作引入了数据同步和一致性问题,所以 Akka 集群采用了 Gossip 协议进行数据同步,通过谁的时间戳最新就以谁为准,来解决一致性问题。

2.2 Redis 集群

除了面向应用程序平台的分布式集群管理之外,分布式数据存储也是一个非常重要的话题。在这其中,分布式数据存储中的集群管理便是一个关键因素。那么接下来,以开源数据库 Redis 的集群管理系统为例,展开介绍吧。

Redis 是一个开源的、包含多种数据结构的高性能 Key-value 数据库,主要有以下特征:

  • 支持多种数据结构,包括字符串(String)、散列(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等;
  • 支持数据的持久化和备份。数据可以保存在磁盘中,下次直接加载使用,且可以采用主从模式(Master/Slave)进行数据备份。
  • 基于内存运行,具有极高的性能

Redis 的这些特征均是为数据存储进行服务的,数据可分片存储在不同的 Redis 节点上,多个 Redis 节点间可共享数据,而提供这项能力的就是 Redis 集群。

Redis 集群中不存在中央节点,是典型的去中心化结构,每个节点均可与其他节点通信。所有节点均可负责存储数据、记录集群的状态(包括键值到正确节点的映射),客户端可以访问或连接到任一节点上。当然,节点之间的数据传输仍采用了 Gossip 协议,来保证集群中数据的最终一致性。

Redis 集群中的节点用于数据存储,所以在设计时,需要考虑数据的可靠性分片存储问题。

对于可靠性的问题,集群中每个节点均存在主备,也就是说每台服务器上都运行两个 Redis 服务,分别为主备,主故障后,备升主。

而对于数据的分片存储问题,Redis 集群引入了“哈希槽”的这一概念。Redis 集群内置了 16384 个哈希槽,每个节点负责一部分哈希槽。当客户端要存储一个数据或对象时,Redis 先对 key 进行 CRC16 校验,然后进行 16384 取模,也即 HASH_SLOT = CRC16(key) mod 16384,来决定哈希槽的编号,从而确定存储在哪个节点上。

比如,当前集群有 3 个节点,那么:

  • 节点 A 包含 0 到 5500 号哈希槽;
  • 节点 B 包含 5501 到 11000 号哈希槽;
  • 节点 C 包含 11001 到 16383 号哈希槽。

Redis 集群利用哈希槽实现了数据的分片存储,从而将 Redis 的写操作分摊到了多个节点上,提高了写并发能力。

Redis 集群是一个非集中式集群管理系统,没有中心节点,不会因为某个节点造成性能瓶颈,每个节点均支持数据存储,且采用分片存储方式,提高了写的并发能力。同时,每个节点的设计采用主备设计,提高了数据的可靠性。

鉴于这些优点,Redis 已被 Twitter、Uber、GitHub、Instagaram 等公司采用。

Redis集群的问题

Redis集群成员管理使用gossip协议,所有节点都对等,管理节点的加入与退出,经过算法收敛,每个节点都能知道完整集群状态,即存在多少节点、每个节点存储的数据槽区间;在数据存储层面,每一个数据分片存储在一主多备的多个节点上,每个数据分片的主节点通过Raft算法选举产生。这样从集群成员管理和数据主备存储两个层面理解,就不矛盾了。

 https://www.cnblogs.com/zhonglongbo/p/13128955.html

2.3 Cassandra 集群

除了 Redis 外,还有一个开源分布式 key-value 数据库系统 Cassandra。Cassandra 也支持数据的分布式存储和操作。因此,Cassandra 的集群架构与数据分片存储方案,与 Redis 集群类似。

如下图所示,Cassandra 集群的系统架构是基于一致性哈希的完全 P2P 结构,没有 Master 的概念,所有节点都是同样的角色,彻底避免了因为单点问题导致的系统不稳定。Cassandra 集群节点间的状态同步,也是通过 Gossip 协议来进行 P2P 通信的。

在 Cassandra 集群中,每次客户端可以向集群中的任意一个节点请求数据,接收到请求的节点将 key 值进行哈希操作,找出在一致性哈希环上是哪些节点应该存储这个数据,然后将请求转发到相应节点上,并将查询结果反馈返回给客户端。

目前,Cassandra 集群因为完全去中心化的结构模式,已经被 Hulu、Apple、Comcast、Instagram、Spotify、eBay、Netflix 等公司使用。

Cassandra 采用去中心化的架构,解决了集中式结构的单点故障问题,同时因为数据基于哈希值分区存储,提高了读写数据的并发能力。在 Cassandra 集群中,没有 Master 的概念,每个节点代表一个哈希值,通过哈希映射的方式决定数据存储的位置。集群间的状态同步通过 Gossip 协议来进行 P2P 的通信。

2.4 总结

如何优化 Gossip 协议中的重复消息问题?

非集中式结构的通信协议采用了 Gossip 协议。而 Gossip 是一种谣言传播协议,每个节点周期性地从节点列表中选择 k 个节点,将本节点存储的信息传播出去,直到所有节点信息一致,即算法收敛了。

这里有个问题,如果每次都是随机选择 k 个节点的话,势必会存在重复选择同样节点的可能,增加消息量。又应该如何优化呢?

解决方案是,每个节点记录当前传输的消息且还未达到收敛的时候,已经发送给了哪些节点,然后每次选择时从没有发送过的节点列表中随机选择 k 个节点,直到所有节点均被传输或集群收敛为止。这样,一方面减少了重复消息量,另一方面加快了收敛速度。

3 个集群的主要特征对比

作者:王陸

-------------------------------------------

个性签名:罔谈彼短,靡持己长。做一个谦逊爱学的人!

本站使用「署名 4.0 国际」创作共享协议,转载请在文章明显位置注明作者及出处。鉴于博主处于考研复习期间,有什么问题请在评论区中提出,博主尽可能当天回复,加微信好友请注明原因

原文地址:https://www.cnblogs.com/wkfvawl/p/15675613.html