一致性、故障域与可用性
CAP 不是屠龙术,它每天都在决定你的集群在断电时丢不丢数据。
学完这节你能做到
- 区分强一致、最终一致在运维上的可观察差异
- 按机架/电源/交换机划分故障域
- 解释 quorum 与脑裂,并说明为什么监控节点要奇数个
CAP 不是屠龙术
CAP 定理常被当成面试题背诵,但它在运维里有非常具体的含义:当网络分区发生时,你的系统是选择拒绝服务,还是选择返回可能不一致的数据。
Ceph 的选择很明确:保一致性,牺牲可用性。MON 失去 quorum 时,整个集群停止服务而不是分裂成两半各自接受写入。这个选择的后果你会天天遇到:
- MON 挂到不足半数 → 集群完全不可用,即使数据都好好的
- PG 的副本数不足
min_size→ 该 PG 拒绝服务,而不是用剩下那份继续写
新人常觉得"太保守了,有一份也该让我写啊"。但想想反面:如果允许,网络恢复后两边各有一份不同的数据,谁是对的?没有答案,只能丢一份。宁可停服,不可分裂——这是存储系统的基本立场。
强一致与最终一致,运维上看到什么
| 强一致 | 最终一致 | |
|---|---|---|
| 写返回后立刻读 | 一定读到新值 | 可能读到旧值 |
| 代表系统 | Ceph RBD/CephFS、GPFS | S3 跨区域复制、多站点 RGW |
| 代价 | 写要等所有副本确认,延迟高 | 写快,但应用要容忍旧数据 |
| 排障特征 | 慢 | 数据"对不上" |
Ceph 的 RADOS 是强一致的:客户端写入必须等所有副本落盘才返回。所以你不会遇到"刚写完读不到"的问题,但你会遇到"某个 OSD 慢导致所有写都慢"。
而 RGW 的多站点复制是最终一致的:主站点写入后异步复制到从站点。这时"刚上传的对象在另一个站点查不到"是正常行为,不是故障。搞不清这一点,会把正常现象当成事故来查。
quorum 与脑裂
quorum(法定人数)的规则朴素得让人怀疑:过半数。
3 个节点 → quorum = 2 → 容忍挂 1 个
5 个节点 → quorum = 3 → 容忍挂 2 个
7 个节点 → quorum = 4 → 容忍挂 3 个
为什么过半数就能防脑裂?因为两个不相交的集合不可能同时都占过半数。网络分区成 2 + 1 时,只有 2 那边能凑齐 quorum 继续服务,1 那边自己知道自己不够,主动停止——不会出现两边都以为自己是主的情况。
4 个节点的 quorum 也是 3,容忍度和 3 个节点一样(都是挂 1 个),却多了一台机器的故障概率。偶数配置在容错上毫无收益,只增加风险。
这条规则对所有基于 quorum 的组件都成立:Ceph MON、etcd、ZooKeeper、GPFS 的 quorum node。GPFS 官方推荐的仲裁节点数同样是 3、5、7。
GPFS 的 quorum 规则更细一些,与恢复组规模挂钩:
scale-out 节点数 = 4 → quorum 节点数 3
scale-out 节点数 = 5 或 6 → quorum 节点数 5
scale-out 节点数 ≥ 7 → quorum 节点数 7
失去 quorum 的后果也一样:GPFS 会卸载整个集群的文件系统,直到 quorum 重建,然后执行文件系统恢复。
min_size:那条容易被改错的线
Ceph 的每个池有两个参数:
ceph osd pool get rbd size # size = 3,副本总数
ceph osd pool get rbd min_size # min_size = 2,最少几个副本在线才提供服务
min_size = 2 意味着:3 副本掉到 2 份还能读写,掉到 1 份就拒绝服务。
出故障时,把 min_size 改成 1 能"立刻恢复业务",所以它是运维手里最诱人也最危险的按钮。
min_size=1 时,集群会用仅剩的那一份数据继续接受写入。如果这份数据所在的盘随后也坏了,或者原来那两个 OSD 带着更老的数据重新上线,就会出现无法判定谁是正确版本的局面——这是真正会丢数据的场景。
正确做法:min_size=1 只作为紧急救火的临时手段,用完立刻改回去,并在恢复完成后复核数据一致性(ceph pg repair / scrub)。把它长期设成 1 等于把 3 副本降级成了 1 副本。
故障域:从盘到机房
冗余只有跨故障域才有意义。Ceph 的 CRUSH 层级默认是:
root
└─ datacenter
└─ room
└─ rack
└─ host
└─ osd
# 查看当前拓扑
ceph osd tree
# 查看规则用的是哪一级故障域
ceph osd crush rule dump replicated_rule
默认规则是 failure-domain=host:三个副本必须落在三台不同主机上。如果机柜级供电是单点,就应该提升到 rack——但这要求你至少有 3 个机架,且每个机架都有足够容量。
判断依据是共因故障的边界在哪:
- 同一台机器的盘共用主板、电源、内核 → 至少 host 级
- 同一机架的机器共用 PDU 和接入交换机 → 有条件就上 rack 级
- 同一机房共用市电和空调 → 关键业务考虑跨机房
但每提升一级,对最少节点数的要求就更高。先保证 host 级是正确的,再谈更高层级。
可用性预算
聊 SLA 时要能把数字换算清楚:
| 可用性 | 年停机时间 |
|---|---|
| 99% | 3.65 天 |
| 99.9% | 8.77 小时 |
| 99.99% | 52.6 分钟 |
| 99.999% | 5.26 分钟 |
关键是 可用性 = MTBF / (MTBF + MTTR)。降低 MTTR 通常比提高 MTBF 更划算:换盘流程从 4 小时压缩到 1 小时,效果远好于采购更贵的盘。这也是为什么值班 SOP、备件库存、自动化工具的投入是有回报的。
某 Ceph 集群 5 个 MON,因机房网络故障分裂成 3 个节点和 2 个节点两个区域。会发生什么?
集群出现 PG 不可用,同事建议把 min_size 从 2 改成 1 让业务先恢复。正确的态度是?
关于可用性,下面哪些说法正确?(多选)
这节课的落点
- 存储系统的基本立场:宁可停服,不可分裂
- 强一致系统的故障表现是"慢",最终一致系统的表现是"数据对不上"
- quorum 必须奇数,偶数配置纯亏;Ceph MON、etcd、GPFS quorum node 同理
min_size=1是应急开关不是配置,用完必须回滚- 故障域按共因故障边界选,先把 host 级做对
- 可用性的抓手是 MTTR,SOP 和演练是有回报的投入