专业书籍精读 · SRE · 第 26 章
Site Reliability Engineering · Ch 26 · Google · 2016
你手机里的照片、几年前的聊天记录、网盘里的合同——你默认它们「一直都在,而且还是原来那样」。这一章讲的就是这件被当成理所当然的事:怎么保证你打开的时候,东西还在、而且没被改坏。写这一章的是两位 Google 工程师,他们管的是 Gmail、Google 云端硬盘这种「丢一条都会上新闻」的系统。
很多人觉得「我存了三份,还怕丢?」——可偏偏就是三份救不了你。你手滑删掉一个文件,那三份会在一秒之内齐刷刷跟着删掉,一份不剩。多存几份防的是「机器坏了」,防不了「人或程序做错了事」。书里那句话很直白:多几份副本,不等于捞得回来。
数据坏掉的方式实在太多:用户手滑、运维敲错命令、程序 bug 批量删、硬盘悄悄变质、机房被水淹。更麻烦的是节奏也不一样——有的是「一下子全没」,你立刻就知道;有的是「一天漏一点」,等半年后发现,最早那批干净的存档都过期清掉了。想用一招通吃是不可能的,所以这一章的答案是:摆三道门。
第一道是回收站。删掉的东西先不真删,打个「已删除」的标记放着,过一阵子才清理干净。它挡的是最常见的那类事故——手滑、被盗号后被人清空。恢复起来几乎不要钱:把标记去掉就行。
第二道是「保险柜里的旧照片」。定期把数据完整地存一份,放到一个离得远、连不上、动不了的地方——Google 用的是磁带。正因为它和线上系统物理断开,你在线上闯的祸传不过去。但关键不在「存没存」,而在「上次真的把它拿出来用过一次吗」。
第三道是「每天点货的管家」。另有一个程序不停地把数据对账:这首歌的档案还指得到那段音频吗?两边的账对得平吗?它挡不住任何一次事故,它的全部价值是让你在用户投诉之前先发现——因为发现得晚一天,保险柜里那份干净的存档就可能已经过期了。
这一章最有用的一句是:别再问「我们备份了吗」,要问「我们上一次真的完整恢复出来,是什么时候」。真实事故里,绝大多数团队的备份任务天天显示成功,只是从来没人试过把它装回去——真到那天,才发现装不回去。诚实说一句代价:三道门都要花真钱(多存一份是成本、天天点货要算力、演练恢复要占人),而且回收站还有个别扭之处——你以为删干净的东西,其实还在某处躺一阵子。
多几份副本防的是机器坏,防不了人和程序做错。真正保命的是三道门:回收站、离线备份、天天点货。判断一个团队靠不靠谱,只需要问一句:你上次真的恢复过一次吗?
想看三道防线的具体机制、选型对比表和真实事故数字? → 切到精读版
这一章把问题反过来定义:数据完整性不是目的,数据可用性才是目的——用户不关心你存了几个副本、校验和对不对,只关心「我要用的时候,东西在不在、对不对」。而能毁掉它的失效模式有 24 种组合,没有任何单一手段挡得住,所以 Google 的答案是纵深防御的三道防线:软删除、备份与恢复、带外校验。全章最扎心的两句是:多副本不等于可恢复;没被验证过恢复的备份,等于没有备份。
SRE 全书第 26 章,属 Part III「实践」里的数据可靠性一组,紧接第 25 章「数据处理管线」——巧的是,管线正是批量毁数据的头号凶手之一。作者 Raymond Blum 与 Rhandeep Singh,长期负责 Gmail、Google 云端硬盘这类「丢一条都算事故」的系统。对应现实:任何长期持有用户数据的服务——邮箱、网盘、SaaS、支付账本、数据仓库。
可用性 SLO 大家都会定:99.9% 的请求成功。但有个尴尬的问题:请求成功了、返回的却是空的,算可用吗?一个刚把用户邮箱清空的系统,完全可以在监控面板上一路绿灯——延迟正常、错误率为零。可用性指标测的是「服务在不在」,不是「数据对不对」。
传统运维对这个问题的答复是「我们有备份」。这一章要拆穿的,正是这句话里的三个洞:备份可能从来没被验证过(GitLab 2017 年出事时,部署的 5 种备份 / 复制手段无一可用);备份可能追不上损坏的速度(Google Music 2012 年误删的约 60 万 条音轨里,有约 16 万 条在被备份到之前就没了);损坏可能根本没人发现,等发现时保留期内的每一代备份都已被坏数据覆盖。
而云时代把这三件事同时放大:更新速率高、持续交付天天改代码、服务之间层层调用、用户 24×7 不给你维护窗口、数据一存就是十几年。不解决的后果不是「慢一点」,而是用户的东西没了,并且永远回不来。
教科书上的「数据完整性」是「数据在整个生命周期里保持准确与一致」。这个定义在工程上不好用——它没告诉你该做到什么程度、该花多少钱。这一章把标尺换成用户视角的数据可用性:服务能不能在用户需要的时候,把正确的数据交到他手里。这一换带来两个直接后果:
所以 SLO 该写成「数据在任何时刻可被正确读取,且任一损坏事件在 X 小时内恢复」,而不是「我们每天做备份」。而且规模会把小概率变成日常:一个存了 100 亿 个对象的系统,就算每个对象一年只有百万分之一的概率静默损坏,一年也有约 1 万 个坏对象等着人处理。
书里把「数据能怎么坏」拆成三个正交的轴:
三轴相乘 = 6 × 2 × 2 = 24 种组合。关键洞察不在这个数字,而在于:任何一种防护都只覆盖其中几格。副本挡硬件与站点灾难,软删除挡误删,备份挡批量损坏——但备份挡不住缓慢渗漏:等你发现时,坏数据早已一代代覆盖进保留期内的所有备份。能挡这一格的只有早发现。所以答案必然是纵深防御,而不是「买个更好的备份方案」。
机制很朴素:删除请求不真删,只给记录打上「已删除」标记和时间戳,读路径自动过滤掉;到期后才真正清除。用户端看到的就是回收站与版本历史。
它凭什么排第一?因为它挡住的是频率最高的那一类事故:用户误删、账号被盗后被恶意清空、运维一次跑错的脚本。这类事故远比机房失火频繁,而它的恢复成本几乎为零——改一个标记位,秒级完成,比从备份里捞快好几个数量级。用「频率 × 恢复成本」算,这是投入产出比最高的一层。
两个工程细节:窗口长度是个真权衡——太短救不回人(用户往往过几天才发现删错了),太长既占存储、又和「彻底删除」的隐私诉求正面冲突,业界常见做法是数周量级(Gmail 回收站 30 天就是这个思路);懒删除(lazy deletion)——真把数据从所有副本、缓存、索引和备份里抹干净,在大规模系统里可能要几周才收敛,这意味着「删除」天然是一个过程而非瞬间。
也要说清它挡不住什么:软删除对付的是「删除」,对付不了「改坏」——应用 bug 把字段算错、写进脏值,回收站里一条都不会有。
这是全章的重心,有三个反直觉的点。
(1)复制不是备份。原文的措辞很不客气:「复制与冗余不等于可恢复性」(Replication and redundancy are not recoverability)。自动同步多副本的数据库,恰恰保证了一次误删、一行被改坏会被推送到所有副本,而且通常在你反应过来之前就完成了。把量级摆出来就很清楚:同步复制的传播延迟是毫秒到秒级,而人类发现问题的时间是分钟到天级——这两个数量级之间的鸿沟,就是副本救不了你的全部原因。
(2)备份不是归档。书里给的判据只有一句:能不能被应用重新加载回去。原文说得很明确——「备份与归档最重要的区别是,备份能被装回应用,归档不能」。备份是为了「装回去继续跑」,所以格式、schema、依赖版本都得和当前系统对得上;归档是为了合规与审计长期封存,可能压根装不回去。把归档当备份,是事故复盘里的常客。
(3)备份策略从恢复需求倒推。别先问「多久备一次」,先问三件事:能容忍丢多少数据(RPO)→ 决定备份频率与要不要重放事务日志;能容忍多久恢复不了(RTO)→ 决定介质与位置;要挡住 24 格里的哪几格 → 决定隔离程度。同集群的快照挡不住「误删被同步过去」,所以必须另有离线、异构、异地的一份。Google 在这一层选了磁带——慢得离谱,但胜在物理上与线上系统断开,任何在线的错误操作都传不过去;2011 年 Gmail 那次正是靠它救回来的。
成本也要算诚实:全量备份最简单,但存储与耗时随数据量线性涨;增量 / 差分省空间,恢复却要按顺序一层层叠加,链条越长越容易断。真实系统通常是「周期性全量 + 期间增量 + 保留 N 代」,而保留几代由「你最晚可能多久才发现损坏」决定——绕一圈又回到缓慢渗漏那一格。
前两道防线都是事后的:它们让你能把数据捞回来,前提是你知道数据坏了。第三道防线专门解决「知道」:跑一批独立于主服务的校验器(validator)持续对账——引用是否悬空(一条歌曲元数据指向的音频文件还在不在)、跨库的账是否平、副本之间是否一致、业务不变量是否成立。
它为什么必须存在:系统越快、越自动,把损坏传播完所需的时间就越短,而人类发现问题的时间并没有变快。校验器的价值,是把「发现延迟」从「等用户投诉」(天)压到「下一轮校验」(分钟到小时)——这直接决定了你还能不能在保留期内找到一份干净的备份。Google Music 那次就是反例:问题是靠工程师排查「某首歌放不出来」才顺藤摸瓜发现的,彼时已有约 16 万条音轨过了能被救回的窗口。
三条实践要点:必须带外——用独立的读路径与部署,别和被检查的系统共用同一套可能有 bug 的代码,否则 bug 会同时骗过服务和校验器;校验器自己也要被监控——一个悄悄停掉的校验器比没有校验器更危险,因为它给的是虚假的安全感;告警要可定位——只报「有 N 条对不上」没用,要能指出是哪些记录、从哪个版本开始的。
最容易被跳过的一步:没被演练过的恢复流程,默认它是坏的。SRE 把「恢复」当成需要持续测试的产品功能——定期做端到端演练(Google 的 DiRT 灾难恢复演练就是这个思路),验收标准是「数据被真正加载回应用、业务校验通过」,不是「备份任务返回成功」。这一章把它收束到 SRE 的几条通用原则上:保持初学者心态(别假设,去查)、信任但要验证、「指望它没事」不是策略(hope is not a strategy),以及纵深防御本身。
表 1 · 三道防线:各挡什么、多快、代价多少
| 第一道 · 软删除 | 第二道 · 备份与恢复 | 第三道 · 带外校验 | |
|---|---|---|---|
| 主要挡住 | 用户误删、盗号清空、一次跑错的脚本 | 应用 bug 批量毁数据、站点灾难、介质损坏 | 什么都不挡——它只负责「早发现」 |
| 恢复速度 | 秒级(改标记位) | 小时到天(取决于介质与带宽) | 不产生恢复能力 |
| 覆盖频率 | 最常见的那一类事故 | 较罕见但破坏面大 | 覆盖「缓慢渗漏」这一格,别处都覆盖不到 |
| 主要代价 | 存储占用;与「彻底删除」的隐私诉求冲突 | 存储 + 演练人力;恢复期业务受损 | 持续算力;校验器本身要被监控与维护 |
| 挡不住 | 数据被改坏(不是删除);绕过软删除层的底层操作 | 缓慢渗漏——发现时保留期内各代都已被污染 | 它救不回任何一个字节 |
表 2 · 复制 / 备份 / 归档:三件最常被混为一谈的事
| 复制 replication | 备份 backup | 归档 archive | |
|---|---|---|---|
| 为了什么 | 机器 / 机房挂了仍能读写 | 出事时能把数据装回去继续跑 | 合规、审计,长期封存 |
| 能否装回应用 | 不涉及(本来就在线) | 能——这是它的定义 | 通常不能 |
| 面对误删 | 毫秒内同步删除,帮凶 | 能捞回(在保留期内) | 可能捞得到内容,但装不回系统 |
| 典型延迟 / 隔离 | 毫秒~秒,零隔离 | 小时~天,需离线 / 异地 / 异构 | 天~周,强隔离 |
| 常见误用 | 「我们有多可用区」当成备份 | 只监控备份成功率、从不验证恢复 | 拿归档当备份,出事才发现装不回 |
表 3 · 备份介质与位置怎么选(按恢复需求倒推)
| 方案 | 典型 RTO | 隔离程度 | 成本 | 什么时候选它 |
|---|---|---|---|---|
| 同集群快照 | 分钟级 | 低——误删 / 恶意删可能一并波及 | 低 | 作为最快的一层,配合软删除用;不能当唯一防线 |
| 异地对象存储 (开版本 / 对象锁) | 小时级 | 中高——跨地域,且可设为不可变 | 中 | 今天多数团队的主力方案;恢复受带宽限制 |
| 离线磁带 | 一天以上 | 最高——物理断开 | 单位存储最低,取回最慢 | 最后一道防线;Google 的 Gmail 正是靠它救回 |
| 连续日志 / WAL 重放 | 看重放量 | 随日志存放位置而定 | 中高 | 要把 RPO 压到分钟级、能接受重放耗时时 |
算一笔恢复的账:RTO 常常不是「策略问题」而是「物理问题」。要从异地把 100 TB 拉回来,就算跑满 10 Gbps,理论上也要约 22 小时——如果你的 RTO 写着「4 小时」,那就不是加钱买存储能解决的,得改架构(分片并行恢复、就近副本、优先恢复热数据)。没算过这笔账的 RTO,都是许愿。
这一章之所以是数据类系统的必读,是因为它把一句人人会说的空话——「我们有备份」——变成了可被审计的具体清单:软删除窗口多少天?上一次完整恢复演练在什么时候、耗时多久?校验器覆盖了哪些不变量、它自己上次跑成功是什么时候?这套问法早已渗进行业:对象存储的版本控制与对象锁本质就是「软删除 + 不可篡改的备份」,数据仓库的 time travel 是软删除的另一种形态,数据可观测性工具做的就是第三道防线的商业化,而「恢复演练」成了金融与云厂商的合规硬指标。放到架构评审和面试里,它给你三句能一击戳破的话:多可用区不等于备份、备份成功率不等于恢复成功率、校验器没被监控等于没有校验器。
0.02% 的 Gmail 用户看到空邮箱,Google 最终从磁带备份把邮件恢复回来——验证了「最后一道防线必须离线、异构」:在线副本再多,也一起中招了。Google SRE Book, Ch.26 Data Integrity ↗60 万 条音轨;最终只有 436,223 条从磁带找回,约 16 万 条在被备份到之前就已丢失——反证了「早发现」比「备份得更多」更关键,问题是靠工程师排查一首放不出来的歌才发现的。Google SRE Book, Ch.26 Data Integrity ↗5 种备份 / 复制手段无一可用(S3 上传静默失败、pg_dump 版本不匹配、告警邮件配置错),最终丢失约 6 小时数据、约 5000 个项目与 700 个新账号——用最惨烈的方式验证了「没被验证过恢复的备份不算备份」。GitLab「Postmortem of database outage of January 31」, 2017 ↗43 秒的网络中断触发自动选主,两地数据库各自接收写入而分叉,随后花了 24 小时 11 分钟做数据调和与降级服务——验证了「复制解决的是可用性,不是数据正确性」。GitHub Blog「October 21 post-incident analysis」, 2018 ↗① 一句话:数据完整性是手段,数据可用性才是目的——用户只关心「要用的时候,正确的数据在不在」。
② 可用性 SLO 测不出数据问题:一个把邮箱清空的系统可以监控全绿;恢复时间也是可用性的一部分。
③ 失效模式 = 根因(6)× 范围(2)× 速率(2)= 24 种组合,没有银弹,只能纵深防御。最难的一格是缓慢渗漏——备份救不了它,只有「早发现」能。
④ 第一道防线 软删除:挡最高频的误删 / 盗号清空,恢复是秒级;窗口长度与隐私诉求是真权衡;它挡不了「改坏」。
⑤ 第二道防线 备份与恢复:复制与冗余不等于可恢复性;备份能装回应用、归档不能;策略从 RPO / RTO 倒推,Google 用磁带正是图它物理断开。
⑥ 第三道防线 带外校验:不阻止事故,只把发现延迟从「天」压到「分钟」;必须独立部署、自己也被监控、告警可定位。
⑦ 没演练过的恢复流程默认是坏的:验收标准是「数据装回应用、业务校验通过」,不是「备份任务成功」。
⑧ RTO 常是物理问题:100 TB 跑满 10 Gbps 也要约 22 小时——没算过账的 RTO 都是许愿。
⑨ 三个数字:Gmail 2011 靠磁带救回 0.02% 用户的邮件;Google Music 2012 约 16 万 条音轨在备份到之前就没了;GitLab 2017 的 5 种备份手段无一可用。
⑩ 评审杀手锏三问:多可用区不等于备份、备份成功率不等于恢复成功率、你上次完整恢复演练是什么时候。