SStorpath
原理预计 30 分钟

一致性、故障域与可用性

CAP 不是屠龙术,它每天都在决定你的集群在断电时丢不丢数据。

学完这节你能做到

  • 区分强一致、最终一致在运维上的可观察差异
  • 按机架/电源/交换机划分故障域
  • 解释 quorum 与脑裂,并说明为什么监控节点要奇数个

CAP 不是屠龙术

CAP 定理常被当成面试题背诵,但它在运维里有非常具体的含义:当网络分区发生时,你的系统是选择拒绝服务,还是选择返回可能不一致的数据。

Ceph 的选择很明确:保一致性,牺牲可用性。MON 失去 quorum 时,整个集群停止服务而不是分裂成两半各自接受写入。这个选择的后果你会天天遇到:

  • MON 挂到不足半数 → 集群完全不可用,即使数据都好好的
  • PG 的副本数不足 min_size → 该 PG 拒绝服务,而不是用剩下那份继续写

新人常觉得"太保守了,有一份也该让我写啊"。但想想反面:如果允许,网络恢复后两边各有一份不同的数据,谁是对的?没有答案,只能丢一份。宁可停服,不可分裂——这是存储系统的基本立场。

强一致与最终一致,运维上看到什么

强一致最终一致
写返回后立刻读一定读到新值可能读到旧值
代表系统Ceph RBD/CephFS、GPFSS3 跨区域复制、多站点 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 的真实代价

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 和演练是有回报的投入