️This article has been over 1 years since the last update.
本文总结一下常见的分布式与高可用方案
什么是分布式系统
定义一: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.
分布式系统一般讨论的是高可用中的可靠性的组合场景,比如冗余或者切片。
分布式不等于高可用(availability),不等于高可靠(durability),不等于弹性伸缩,不等于冗余,不等于克服了单点故障,也不提供掉电保护。
硬件分布式系统分类
硬件上主要体现在冗余性,虚拟直通,存算分离上
上述可以确保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 
按照组网架构分类
常见组网架构如下
上述方案假设在高速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 | 自动恢复 | 读写分离 | 
|---|---|---|---|---|
| Jenkins | NFS/rsync innotify | 0 | 需要手动 | NA | 
| GitLab(unofficial) | NFS/rsync innotify | keepalived | Y | 勉强够用 | 
| MySQL | Async Binlog | 0 | 需要手动 | N | 
| pg-pool | WAL | 1 | 需要手动 | Y | 
| Redis | Async AOF/RDB | 0 | 需要手动 | N | 
| Redis(Sentinel) | Async AOF/RDB | 1~3(Sentinel) | Y,比如5s | N | 
| Artifactory-Remote | Pull | NA | NA | NA | 
从我个人实践的角度,热主备方案投资收益极为鸡肋
- 大部分都无法扩容,中间的代理层导致应用定位复杂(需要额外的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同步等流程。
路由与失败检查(Failure Models)
这里主要需要纠结pull和push,超时和失败的定义。
总结
只要是异步系统(无法区分超时),共识在有限时间内不能完美地完成
作为技术人员,不要因为面试八股文就陷入100%分布式高可用、弹性伸缩、容灾且完美调度等理想模型中,而是意识到理论的不完美、技术的局限性,现实的不确定性,才能更好地理解分布式系统。
扩容是系统工程,物理机房的密度,交换机的插孔,功耗等都会限制最大值,上述方案最终实现的也不过是“昂贵的数据孤岛”。甚至你在专心搞高可用时,你的友商投入人力做Demo已经把项目拿下了。