4.1 混沌的分布式环境
引入: 分布式计算的谬误
有一组著名的断言,叫做分布式计算的谬误1,指出了新手容易作出的错误假设。
No. | 断言 | |
---|---|---|
1 | The network is reliable | 网络可靠 |
2 | Latency is zero | 延迟为零 |
3 | Bandwidth is infinite | 带宽是无限的 |
4 | The network is secure | 网络是安全的 |
5 | Topology doesn’t change | 拓扑不会改变 |
6 | There is one administrator | 有一个管理员 |
7 | Transport cost is zero | 运输成本为零 |
8 | The network is homogeneous | 网络是同质的 |
这些谬误断言,实际上也指出了分布式系统的重要特性:“失效” 是正常现象。
系统必须将失效作为一等功能去设计和实现。在实际生产工程中,开发者大部分的精力都在和 “失效容忍” 作斗争。
失效是正常的, 但需要建模和约束
虽然我们意识到失效是正常现象,但必须进行事前的建模和约束。下列失效故障的严重程度明显是不一致的:
- 单节点某一个硬盘读性能大幅度下降
- 单节点(18块硬盘)整机掉电
- 机架(10台节点)网络离线
- 整个机房因火灾掉电
而我们的方案的服务质量承诺 (SLA) 必须具有一个前提,比如
SLA 要求 | 技术手段 |
---|---|
单节点掉线仍然无损 | 使用共识算法保证多数派服务正常 |
容忍整个机房的掉线 | 需要两地三中心模式部署 |
不同失效的容忍要求,直接决定了系统的设计和实现,因此必须提前建好模型,定义故障边界。
系统永远不能保证容忍设计者没有考虑过的错误。
故障模型 (Failure Model)
故障模型用于描述系统能够容忍的抽象失效。在设计系统前,明确故障模型也非常重要。 文章2 很好地总结了几种常见的故障模型和应对手段。
故障失效模型 | 定义 | 特征 |
---|---|---|
Fail-stop Failures | 系统组件完全停止运行,其故障能立即被系统其他部分察觉,不再发送或接收消息 | - 组件停止且易检测 - 无部分故障或异常行为 - 适用于有故障转移机制的系统 |
Crash Failures | 组件故障并停止运行,但故障可能不会立即被系统其他部分发现 | - 组件无声崩溃,不立即报警 - 需通过超时或通信错误检测 - 系统可能错误地继续与故障组件交互导致延迟 |
Omission Failures | 系统组件未能发送或接收消息,可分为发送遗漏(组件未能发送消息)和接收遗漏(组件未能接收消息) | - 系统继续运行,但消息丢失或未送达 - 可能导致性能下降或数据过时 - 组件本身看似正常,难以检测 |
Temporal Failures | 系统组件在预期时间框架外传递消息,导致性能下降或操作顺序错误 | - 组件发送或接收消息过早或过晚 - 可能导致数据不一致、竞争条件或同步问题 - 对延迟敏感的应用尤其脆弱 |
Byzantine Failures | 组件行为不可预测或恶意,向系统不同部分发送冲突或错误数据 | - 组件可能行为不一致或恶意 - 故障不可预测,可能涉及损坏或伪造的消息 - 需要检测和缓解冲突状态 |
Network Partitions | 组件间通信中断,但每个组件继续独立运行,可能导致“分裂大脑”场景 | - 组件独立运行,导致状态分歧 - 恢复复杂,尤其是在出现显著分歧时 |
Arbitrary Failures | 由硬件问题、内存损坏或软件错误导致的不可预测故障,不遵循标准模式 | - 行为不稳定,难以重现 - 可能导致数据丢失或损坏 |
是否要考虑拜占庭问题?
拜占庭失效是指组件可能向系统不同部分发送冲突或错误数据。比如外部黑客的恶意数据。
一般在公司内网运行的服务,不考虑拜占庭问题。
公共服务,比如 ipfs、以太坊网络,必须要将拜占庭问题作为首要需求考虑。
单向联通的网络分区?
一般模型的 Network Partitions 是指网络的中断,包括发包和收包。单向联通常见于 iptable 的错误配置。在实际工程中,笔者会使用简单的拨测策略检测各节点中的网络情况。
磁盘故障模式
在存储领域,磁盘故障主要分为以下几种
磁盘故障类型 | 故障性质 | 处理措施 |
---|---|---|
磁盘读写性能大幅下降 (Slow) | 临时故障或永久故障 | 隔离磁盘,降低磁盘读写权重 |
磁盘无响应 (Hang) | 永久故障 | 超时后隔离该磁盘,立即启动数据迁移 |
磁盘数据损坏 (EIO) | 永久故障 | 立即标记磁盘错误,立即启动数据迁移 |
进一步获取 kernel 日志,分析磁盘失效原因,预测磁盘故障是更佳的。
机械硬盘的故障率
机械硬盘的年故障率(Annualized Failure Rates, AFR)一般参考云存储服务商 Backblaze 发布的报告3。整体大致在 1% - 2% 左右,但不同品牌、型号差异较大。
系统设计应至少满足该故障率的随机磁盘故障。实际还要要考虑整个节点的整体故障,因此系统应该容忍更高的故障率。
从运维视角思考
谬误断言中有一条叫做 There is one administrator (只有一个管理员)。笔者也是实际参与一些工作后体会到,整个方案的设计如何做到运维友好。
故障的处理、参数调控尽量做到简单有效。
若从运维同事的角度,下面哪个方案更容易接受呢?
对比维度 | 方案A(多参数手动配置) | 方案B(单参数自动调速) |
---|---|---|
参数数量 | 5个(基础速率、时段系数、用户组权重等) | 1个(目标带宽占用率) |
配置方式 | 需在3个窗口手动填写,需校验参数关联性 | 单个窗口填写,系统自动处理细节 |
运维操作复杂度 | 高(需熟记参数依赖关系,多窗口切换) | 低(仅需设置核心目标,无需人工干预) |
故障处理方式 | 需人工分析参数配置是否冲突,手动调整多个参数 | 系统自动检测网络状态,自动回落至安全速率 |
对运维经验依赖度 | 高(依赖管理员个人知识储备) | 低(无需深入理解调速逻辑,傻瓜式操作) |
很显然是方案 B 更有持续性。
笔者曾经在某个系统中设计了类似 A 的方案,以求锦上添花的效果。但是方案不直观导致的中间沟通成本,交付消耗了大量的时间。
可观测性先行
近年来可观测技术已经成为事实标准,比如 Prometheus + Grafana、OpenTelemtry 等。
在系统初期,也应该在关键路径加入不同分位的观测指标,开发者应当对系统的瓶颈有很清晰的认识。尤其是分析性能问题时,极为有用。
整个分布式系统应当是个白盒模式,而不是黑盒+日志模式。
小结
本节从《分布式系统的几个谬误》出发,描述了笔者对于分布式环境的混沌性质的理解。
部分理论的认识确实是经过实践才能体会到,希望能和读者一同交流学习。