常见分布式系统介绍
2021-08-04 / modified at 2024-06-01 / 2.5k words / 10 mins

本文总结一下常见的分布式与高可用方案

什么是分布式系统

定义一:A distributed system is a collection of autonomous computing elements that appears to its users as a single coherent/koˈhɪrǝnt/ system.

翻译过来,就是对用户看起来是单体,但是实际上是由独立自治的计算组件聚合而成的系统。

  • autonomous: having the freedom to act independently.
  • computing elements: node, can be HPC, VM, Thread and more.
  • collection: is often organized as an overlay network. Eg: p2p, TCP/IP
  • coherent: a distributed system is coherent if it behaves according to the expectations of its users. 注意这里是用户对主观现象的观测,而非客观的定义,如果换个较真的人观察出破绽,那么它就是不是"单体"了。

定义二:A distributed system consists of a collection of distinct processes which are spatially separated, and which com- municate with one another by exchanging messages

一个分布式系统是多个空间上分离,使用内部通信的独立流程组合的集合。

从这里的定义可以看出,分布式系统是一个经验归纳大于理论演绎的定义。它涉及到了同一(identity)关系的哲学问题(忒修斯之船),与时间颗粒度息息相关。

机房里的CPU换了2次,内存换了3次,它还是这套集群吗?虚拟机通过热迁移技术切换到另一个机柜的设备中,它还是你的VM吗?

可靠和可用

High availability (HA) is a characteristic of a system which aims to ensure an agreed level of operational performance, usually uptime, for a higher than normal period.

$2resilience可靠性:(无故障时间)/(无故障时间 + 1)通过客观的器件失效得到的统计数据,不涉及修复。原子系统:比如元件老化/温度等客观的统计数据。组合系统:涉及到原子系统的串联/并联组合可用性:(无故障时间)/(无故障时间+修复时间)提高无故障时间(可靠性)提高修复速度

分布式系统一般讨论的是高可用中的可靠性的组合场景,比如冗余或者切片。

分布式不等于高可用(availability),不等于高可靠(durability),不等于弹性伸缩,不等于冗余,不等于克服了单点故障,也不提供掉电保护。

硬件分布式系统分类

硬件上主要体现在冗余性,虚拟直通,存算分离上

$2硬件交付机柜可用性双光口交换冗余电源/UPS跨机柜部署(风水电)机房可用性跨可用区(AZ)部署OpenStack/私有云(eg: HCS)计算虚拟化完全虚拟化/emulateDMA直通裸金属存储对象存储基于对象存储的分布式存储块存储/云硬盘RoCE(本质上仍然是复制)SDN

上述可以确保VM与内存数据几乎不会丢失,但是VM中运行的软件本身仍然可能挂掉。

软件分布式系统分类

理论的维度

假如需要进行专业的体系化CS课程,至少半年,可以参考如下

  • Distributed Computing Systems(cs230)

    • 时间:物理时间(比如ntp同步)与逻辑时间(比如term)

    • 状态:全局状态与快照

    • Distributed Coordination and Resource Management

    • Messaging and Communication in Distributed Systems

    • Fault Tolerance in Distributed Systems

  • Security in Distributed Systems

  • Distributed Database Management and Transaction Processin(cs223)

  • Distributed Objects and Middleware Platforms(cs237)

这里理论比工程更重要,而且是存粹的理论。

工程上的规格

假如只是进行概念的理解,如下即可

  • 一致性:强一致性、最终一致性

  • 需要分布管理的内容:比如

    • 元数据(比如k-v、状态、健康)
    • 二进制(比如S3/Git/SVN/Lustre/边缘SDN)
  • 协商方向:

    • Push:下游需要全量数据时才使用,比如Database streaming/mirroring,RAFT
    • Pull:下游需要部分数据即可,如二进制增量缓存/看门狗等场景
    • Proxy:比如Gitlab geo的写入方案,cloudflare的Worker读写方案
  • 节点角色:广义上也可以看作政治权利,比如说“不”的权利。

  • 故障转移时间RTO:一般商用需要为10s

按照组网架构分类

常见组网架构如下

$2单机/Stateless主从两机(primary/secondary)热备挂了立刻只读自动failover切换冷备三台以上选举/复制/转发/路由

上述方案假设在高速LAN中横向通信,不含容灾。上述成本基本上都比托管的服务更高,也不包含硬件存储架构方案。
事实上云服务厂商的硬件实现的分布式存储才是最简方案。

工程经验类方法

工程实践的核心思路是将本侧的分布式难题交给下游供应商,进而提高收益,比如

  • 将业务分解为meta/worker/proxy等无状态的服务,比如sonarqube的ComputeEngine

  • 用硬件的RDMA/NFS转换问题,比如Oracle RAC就强制要求超高性能内网,否则直接停机。

  • 用软件的数据库/Raft,基于元数据实现分片,比如在三个数据中心搭建2+2+1的高可用的quorum

  • 用云服务,比如FSFO(by Oracle),或者GaussDB参考,用Aurora把难题扔给AWS。然而云服务事实上并不兜底,最多赔偿一点代金券,相对业务损失不值一提。

主备方案介绍

大部分有状态的主备份方案为冗余方案(hot standby),难点在同步复制协议(Primary/Replica)。它要求的性能与可用性(断电前写入存储介质)中取得平衡

  • 协议:主要为基于Journaling的checkpoint和reply的方案
  • 强一致类型:写入IO性能变弱,可以实现读写分离,任意一台挂掉需要人工介入
  • 最终一致类型:基本上就是靠事件+定时同步,可以容灾

常见如下

类型复制协议Monitoring node自动恢复读写分离
JenkinsNFS/rsync innotify0需要手动NA
GitLab(unofficial)NFS/rsync innotifykeepalivedY勉强够用
MySQLAsync Binlog0需要手动N
pg-poolWAL1需要手动Y
RedisAsync AOF/RDB0需要手动N
Redis(Sentinel)Async AOF/RDB1~3(Sentinel)Y,比如5sN
Artifactory-RemotePullNANANA

从我个人实践的角度,热主备方案投资收益极为鸡肋

  • 大部分都无法扩容,中间的代理层导致应用定位复杂(需要额外的Client/Agent 来判活,比如pg-pool的连接池在项目中出现2次大故障,定位起来资料困乏)
  • 冗余框架出了问题仍然要手动维修,万一真挂了,重启也修不好
  • 自动切换需要客户端适配协商,引入繁琐的非业务用例,比如需要做“监控的监控”

上述方案其实意义有限,甚至整体恢复时间不如单机版+极速备份回滚

三台以上高可用方案

一致性与过期(consistance and stale)的定义

谈到一致性,很多人就想到了被阿里带歪的CAP八股文,我们要先明确

  • 一致需要同时考虑客户端与服务端的配置,你搭建三台号称强一致性的ZK,并不代表业务就有了强一致性
  • CAP并不是要求三选二,而是大部分情况“我全都要”,而且主要是客户端自己决定

举一些例子

  • 当etcd挂了,K8S里的应用服务仍然能跑,Calico也勉强能用,客户端缓存还在,只是部分控制域的功能丢失
  • Consul既支持客户端绕一圈获取协商结果(network roundtrips,耗时长),也支持直接读取单节点数据,甚至客户端/Sidecar节点本身就有一定缓存
  • Oracle RAC是集群数据库,它需要处理转账等强一致业务,一旦RDMA集群间断网就直接停机。
  • 你在两个数据中心部署了2+3个zk,然后部署三台的机房突然停电,另外两台也照样完蛋。

基于元数据管理的方案

元数据既可以通过集中管理,也可以通过分散管理

  • 分散:区块链、GlusterFS与DHT BT下载等场景,以及跨DC的Github Spokes 服务
  • 集中:常见的BT的tracker协议,以及RAFT/Paxo/Gossip(这里讨论)

我们首先要明确,在中心化的一致性元数据管理中,并没有实现扩容

  • 用于数据面(比如分片)与控制面(比如路由)的元数据存储仍然需要中心化的权威存储介质(have a single primary copy at any moment.),并基于强一致性实现多机冗余。就算是DHT表,也不会同步到所有客户端机器。
  • 剩余节点是无状态运算机,可以扩容

跨WAN的Region场景,默认是不可靠的,一般要最终一致性,这种流程可以简化容灾,跨Site同步等流程。

$2跨DC复制强一致元数据服务Metadata serverZookeeper(PAXO)Etcd(RAFT)Nomad/Consul(RAFT)RedisRaft(RAFT)MetadataRouterKVPartitionCalicoenvoyDHTGlusterFSCephFSLustreSidecar-proxy跨Region复制最终一致性Rsync/Binlog/AOFEurekaGossipPortworx加密类

路由与失败检查(Failure Models)

这里主要需要纠结pull和push,超时和失败的定义。

$2routingheartbeatsTCPhealth probemetricsload statusAPMreal application trafficUpdate StrategyRolling?Drain node?

总结

只要是异步系统(无法区分超时),共识在有限时间内不能完美地完成

作为技术人员,不要因为面试八股文就陷入100%分布式高可用、弹性伸缩、容灾且完美调度等理想模型中,而是意识到理论的不完美、技术的局限性,现实的不确定性,才能更好地理解分布式系统。

扩容是系统工程,物理机房的密度,交换机的插孔,功耗等都会限制最大值,上述方案最终实现的也不过是“昂贵的数据孤岛”。甚至你在专心搞高可用时,你的友商投入人力做Demo已经把项目拿下了。