HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

左耳朵耗子:我对 GitLab 误删除数据库事件的几点思考

  • 2017-02-06
  • 本文字数:5891 字

    阅读完需:约 19 分钟

更多左耳朵耗子的独家干货,请订阅极客时间出品的陈皓全年专栏《左耳听风》,一次订阅、永久阅读。即日起,戳此订阅立享以下两大福利:

福利一:原价 ¥199/ 年,极客时间新用户注册立减 ¥30

福利二:每邀请一位好友购买,你可获得 36 元现金返现,多邀多得,上不封顶,立即提现(提现流程:极客时间服务号 - 我的 - 现金奖励提现)

太平洋时间 2017 年 1 月 31 日晚上,GitLab 通过推特发文承认 300GB 生产环境数据因为 UNIX SA 的误操作,已经被彻底删除(后发文补充说明已经挽回部分数据),引起业界一片哗然。知名博主陈皓在其博客中详细回顾了此次事件,并做了思考和总结,聊聊架构经原作者授权发布此文。

昨天,GitLab.com 发生了一个大事,某同学误删了数据库,这个事看似是个低级错误,不过,因为 GitLab 把整个过程的细节都全部暴露出来了,所以,可以看到很多东西,而对于类似这样的事情,我自己以前也干过,而在最近的两公司中我也见过(Amazon 中见过一次,阿里中见过至少四次),正好通过这个事来说说一下自己的一些感想和观点吧。我先放个观点:你觉得有备份系统就不会丢数据了吗?

事件回顾

整个事件的回顾 GitLab.com 在第一时间就放到了 Google Doc 上,事后,又发了一篇 Blog 来说明这个事,在这里,我简单的回顾一下这个事件的过程。

首先,一个叫 YP 的同学在给 GitLab 的线上数据库做一些负载均衡的工作,在做这个工作时的时候突发了一个情况,GitLab 被 DDoS 攻击,数据库的使用飙高,在 block 完攻击者的 IP 后,发现有个 staging 的数据库 (db2.staging) 已经落后生产库 4GB 的数据,于是 YP 同学在 Fix 这个 staging 库的同步问题的时候,发现 db2.staging 有各种问题都和主库无法同步,在这个时候,YP 同学已经工作的很晚了,在尝试过多个方法后,发现 db2.staging 都 hang 在那里,无法同步,于是他想把 db2.staging 的数据库删除了,这样全新启动一个新的复制,结果呢,删除数据库的命令错误的敲在了生产环境上(db1.cluster),结果导致整个生产数据库被误删除(陈皓注:这个失败基本上就是 “工作时间过长” + “在多数终端窗口中切换中迷失掉了”)。

在恢复的过程中,他们发现只有 db1.staging 的数据库可以用于恢复,而其它的 5 种备份机制都不可用,第一个是数据库的同步,没有同步 webhook,第二个是对硬盘的快照,没有对数据库做,第三个是用 pg_dump 的备份,发现版本不对(用 9.2 的版本去 dump 9.6 的数据)导致没有 dump 出数据,第四个 S3 的备份,完全没有备份上,第五个是相关的备份流程是问题百出的,只有几个粗糙的人肉的脚本和糟糕的文档,也就是说,不但是是人肉的,而且还是完全不可执行的(陈皓注:就算是这些备份机制都 work,其实也有问题,因为这些备份大多数基本上都是 24 小时干一次,所以,要从这些备份恢复也一定是是要丢数据的了,只有第一个数据库同步才会实时一些)。

最终,GitLab 从 db1.staging 上把 6 个小时前的数据 copy 回来,结果发现速度非常的慢,备份结点只有 60Mbits/S,拷了很长时间(陈皓注:为什么不把 db1.staging 给直接变成生产机?因为那台机器的性能很差)。数据现在的恢复了,不过,因为恢复的数据是 6 小时前的,所以,有如下的数据丢失掉了:

  • 粗略估计,有 4613 的项目, 74 forks, 和 350 imports 丢失了;但是,因为 Git 仓库还在,所以,可以从 Git 仓库反向推导数据库中的数据,但是,项目中的 issues 等就完全丢失了。
  • 大约有±4979 提交记录丢失了(陈皓注:估计也可以用 git 仓库中反向恢复)。
  • 可能有 707 用户丢失了,这个数据来自 Kibana 的日志。
  • 在 1 月 31 日 17:20 后的 Webhooks 丢失了。

因为 GitLab 把整个事件的细节公开了出来,所以,也得到了很多外部的帮助,2nd Quadrant 的 CTO – Simon Riggs 在他的 blog 上也发布文章 Dataloss at GitLab 给了一些非常不错的建议:

  • 关于 PostgreSQL 9.6 的数据同步 hang 住的问题,可能有一些 Bug,正在 fix 中。
  • PostgreSQL 有 4GB 的同步滞后是正常的,这不是什么问题。
  • 正常的停止从结点,会让主结点自动释放 WALSender 的链接数,所以,不应该重新配置主结点的 max_wal_senders 参数。但是,停止从结点时,主结点的复数连接数不会很快的被释放,而新启动的从结点又会消耗更多的链接数。他认为,GitLab 配置的 32 个链接数太高了,通常来说,2 到 4 个就足够了。
  • 另外,之前 GitLab 配置的 max_connections=8000 太高了,现在降到 2000 个是合理的。
  • pg_basebackup 会先在主结点上建一个 checkpoint,然后再开始同步,这个过程大约需要 4 分钟。
  • 手动的删除数据库目录是非常危险的操作,这个事应该交给程序来做。推荐使用刚 release 的 repmgr。
  • 恢复备份也是非常重要的,所以,也应该用相应的程序来做。推荐使用 barman (其支持 S3)。
  • 测试备份和恢复是一个很重要的过程。

看这个样子,估计也有一定的原因是——GitLab 的同学对 PostgreSQL 不是很熟悉。

随后,GitLab 在其网站上也开了一系列的 issues,其 issues 列表在这里 Write post-mortem (这个列表可能还会在不断更新中)。

  • infrastructure#1094 – Update PS1 across all hosts to more clearly differentiate between hosts and environments
  • infrastructure#1095 – Prometheus monitoring for backups
  • infrastructure#1096 – Set PostgreSQL’s max_connections to a sane value
  • infrastructure#1097 – Investigate Point in time recovery & continuous archiving for PostgreSQL
  • infrastructure#1098 – Hourly LVM snapshots of the production databases
  • infrastructure#1099 – Azure disk snapshots of production databases
  • infrastructure#1100 – Move staging to the ARM environment
  • infrastructure#1101 – Recover production replica(s)
  • infrastructure#1102 – Automated testing of recovering PostgreSQL database backups
  • infrastructure#1103 – Improve PostgreSQL replication documentation/runbooks
  • infrastructure#1104 – Kick out SSH users inactive for N minutes
  • infrastructure#1105 – Investigate pgbarman for creating PostgreSQL backups

从上面的这个列表中,我们可以看到一些改进措施了。挺好的,不过我觉得还不是很够。

因为类似这样的事,我以前也干过(误删除过数据库,在多个终端窗口中迷失掉了自己所操作的机器……),而且我在亚马逊里也见过一次,在阿里内至少见过四次以上(在阿里人肉运维的误操作的事故是我见过最多的),但是我无法在这里公开分享,私下可以分享。在这里,我只想从非技术和技术两个方面分享一下我的经验和认识。

我的思考:技术方面 人肉运维

一直以来,我都觉得直接到生产线上敲命令是一种非常不好的习惯。我认为,一个公司的运维能力的强弱和你上线上环境敲命令是有关的,你越是喜欢上线敲命令你的运维能力就越弱,越是通过自动化来处理问题,你的运维能力就越强。理由如下:

  1. 如果说对代码的改动都是一次发布的话,那么,对生产环境的任何改动(包括硬件、操作系统、网络、软件配置……),也都算是一次发布。那么这样的发布就应该走发布系统和发布流程,要被很好的测试、上线和回滚计划。关键是,走发布过程是可以被记录、追踪和回溯的,而在线上敲命令是完全无法追踪的。没人知道你敲了什么命令。
  2. 真正良性的运维能力是——人管代码,代码管机器,而不是人管机器。你敲了什么命令没人知道,但是你写个工具做变更线上系统,这个工具干了什么事,看看工具的源码就知道了。

另外,有人说,以后不要用 rm 了,要用 mv,还有人说,以后干这样的事时,一个人干,另一个人在旁边看,还有人说,要有一个 checklist 的强制流程做线上的变更,还有人说要增加一个权限系统。我觉得,这些虽然可以 work,但是依然不好,因为:

  • 如果要解决一个事情需要加更多的人来做的事,那这事就做成劳动密集型了。今天我们的科技就是在努力消除人力成本,而不是在增加人力成本。而做为一个技术人员,解决问题的最好方式是努力使用技术手段,而不是使用更多的人肉手段。人类区别于动物的差别就是会发明和使用现代化的工具,而不是使用更多的人力。另外,这不仅仅因为是,人都是会有这样或那样的问题(疲惫、情绪化、急燥、冲动……),而机器是单一无脑不知疲惫的,更是因为,机器干活的效率和速度是比人肉高出 N 多倍的。
  • 增加一个权限系统或是别的一个 watch dog 的系统完全是在开倒车,权限系统中的权限谁来维护和审批?不仅仅是因为多出来的系统需要多出来的维护,关键是这个事就没有把问题解决在 root 上。除了为社会解决就业问题,别无好处,故障依然会发生,有权限的人一样会误操作。对于 GitLab 这个问题,正如 2nd Quadrant 的 CTO 建议的那样,你需要的是一个自动化的备份和恢复的工具,而不是一个权限系统。
  • 像使用 mv 而不 rm,搞一个 checklist 和一个更重的流程,更糟糕。这里的逻辑很简单,因为,1)这些规则需要人去学习和记忆,本质上来说,你本来就不相信人,所以你搞出了一些规则和流程,而这些规则和流程的执行,又依赖于人,换汤不换药,2)另外,写在纸面上的东西都是不可执行的,可以执行的就是只有程序,所以,为什么不把 checklist 和流程写成代码呢(你可能会说程序也会犯错,是的,程序的错误是 consistent,而人的错误是 inconsistent)?

最关键的是,数据丢失有各种各样的情况,不单单只是人员的误操作,比如,掉电、磁盘损坏、中病毒等等,在这些情况下,你设计的那些想流程、规则、人肉检查、权限系统、checklist 等等统统都不管用了,这个时候,你觉得应该怎么做呢?是的,你会发现,你不得不用更好的技术去设计出一个高可用的系统!别无它法。

关于备份

一个系统是需要做数据备份的,但是,你会发现,GitLab 这个事中,就算所有的备份都可用,也不可避免地会有数据的丢失,或是也会有很多问题。理由如下:

  1. 备份通常来说都是周期性的,所以,如果你的数据丢失了,从你最近的备份恢复数据里,从备份时间到故障时间的数据都丢失了。
  2. 备份的数据会有版本不兼容的问题。比如,在你上次备份数据到故障期间,你对数据的 scheme 做了一次改动,或是你对数据做了一些调整,那么,你备份的数据就会和你线上的程序出现不兼容的情况。
  3. 有一些公司或是银行有灾备的数据中心,但是灾备的数据中心没有一天 live 过。等真正灾难来临需要 live 的时候,你就会发现,各种问题让你 live 不起来。你可以读一读几年前的这篇报道好好感受一下《以史为鉴,宁夏银行 7 月系统瘫痪最新解析》。

所以,在灾难来临的时候,你会发现你所设计精良的“备份系统”或是“灾备系统”就算是平时可以工作,但也会导致数据丢失,而且可能长期不用的备份系统很难恢复(比如应用、工具、数据的版本不兼容等问题)。

我之前写过一篇《分布式系统的事务处理》,你还记得下面这张图吗?看看 Data Loss 那一行的,在 Backups, Master/Slave 和 Master/Master 的架构下,都是会丢的。

所以说,如果你要让你的备份系统随时都可以用,那么你就要让它随时都 Live 着,而随时都 Live 着的多结点系统,基本上就是一个分布式的高可用的系统。因为,数据丢失的原因有很多种,比如掉电、磁盘损坏、中病毒等等,而那些流程、规则、人肉检查、权限系统、checklist 等等都只是让人不要误操作,都不管用,这个时候,你不得不用更好的技术去设计出一个高可用的系统!别无它法。(重要的事,得再说一篇)

另外,你可以参看我的另一篇《关于高可用系统》,这篇文章中以 MySQL 为例,数据库的 replication 也只能达到 两个 9。

AWS 的 S3 的的高可用是 4 个加 11 个 9 的持久性(所谓 11 个 9 的持久性 durability,AWS 是这样定义的,如果你存了 1 万个对象,那么丢一个的时间是 1000 万年),这意味着,不仅仅只是硬盘坏,机器掉电,整个机房挂了,其保证可以承受有两个设施的数据丢失,数据还是可用的。试想,如果你把数据的可用性通过技术做到了这个份上,那么,你还怕被人误删一个结点上的数据吗?

我的思考:非技术方面 故障反思

一般说来,故障都需要反思,在 Amazon,S2 以上的故障都需要写 COE(Correction of Errors),其中一节就是需要 Ask 5 Whys,我发现在 GitLab 的故障回顾的 blog 中第一段中也有说要在今天写个 Ask 5 Whys。关于 Ask 5 Whys,其实并不是亚马逊的玩法,这还是算一个业内常用的玩法,也就是说不断的为自己为为什么,直到找到问题的概本原因,这会逼着所有的当事人去学习和深究很多东西。在 Wikipedia 上有相关的词条 5 Whys,其中罗列了 14 条规则:

  • 你需要找到正确的团队来完成这个故障反思。
  • 使用纸或白板而不是电脑。
  • 写下整个问题的过程,确保每个人都能看懂。
  • 区别原因和症状。
  • 特别注意因果关系。
  • 说明 Root Cause 以及相关的证据。
  • 5 个为什么的答案需要是精确的。
  • 寻找问题根源的频,而不是直接跳到结论。
  • 要基础客观的事实、数据和知识。
  • 评估过程而不是人。
  • 千万不要把“人为失误”或是“工作不注意”当成问题的根源。
  • 培养信任和真诚的气氛和文化。
  • 不断的问“为什么”直到问题的根源被找到。这样可以保证同一个坑不会掉进去两次。
  • 当你给出“为什么”的答案时,你应该从用户的角度来回答。

工程师文化

上述的这些观点,其实,我在我的以住的博客中都讲过很多遍了,你可以参看《什么是工程师文化?》以及《开发团队的效率》。其实,说白了就是这么一个事——如果你是一个技术公司,你就会更多的相信技术而不是管理。相信技术会用技术来解决问题,相信管理,那就只会有制度、流程和价值观来解决问题。

这个道理很简单,数据丢失有各种各样的情况,不单单只是人员的误操作,比如,掉电、磁盘损坏、中病毒等等,在这些情况下,你设计的那些流程、规则、人肉检查、权限系统、checklist 等等统统都不管用,这个时候,你觉得应该怎么做呢?是的,你会发现,你不得不用更好的技术去设计出一个高可用的系统!别无它法(重要的事得说三遍)。

事件公开

很多公司基本上都是这样的套路,首先是极力掩盖,如果掩盖不了了就开始撒谎,撒不了谎了,就“文过饰非”、“避重就轻”、“转移视线”。然而,面对危机的最佳方法就是——“多一些真诚,少一些套路”,所谓的“多一些真诚”的最佳实践就是——“透明公开所有的信息”,GitLab 此次的这个事给大家树立了非常好的榜样。AWS 也会把自己所有的故障和细节都批露出来。

事情本来就做错了,而公开所有的细节,会让大众少很多猜测的空间,有利于抵制流言和黑公关,同时,还会赢得大众的理解和支持。看看 GitLab 这次还去 YouTube 上直播整个修复过程,是件很了不起的事,大家可以到他们的 blog 上看看,对于这样的透明和公开,一片好评。

2017-02-06 16:524950

评论

发布
暂无评论
发现更多内容

Vue是怎样监听数组的变化的?

bb_xiaxia1998

Vue

11月月更开启啦!冬天到了,不写点东西暖暖身子吗?

InfoQ写作社区官方

热门活动 11月月更

前端高频手写题自测,你能做出几道

helloworld1024fd

JavaScript

应用实践:Paddle分类模型大集成者[PaddleHub、Finetune、prompt]

汀丶人工智能

nlp 文本分类 关系抽取 命名实体识别 11月月更

面试官:请实现Javascript发布-订阅模式

helloworld1024fd

JavaScript

20道高级前端面试题解析

loveX001

JavaScript

React-Hooks怎样封装防抖和节流-面试真题

beifeng1996

React

怎样刷vue面试题

bb_xiaxia1998

Vue

这可能是你需要的vue考点梳理

bb_xiaxia1998

Vue

这些js原型及原型链面试题你能做对几道

loveX001

JavaScript

前端八股文总结

loveX001

JavaScript

React-Hooks源码深度解读

goClient1992

React

爆肝整理高频js手写题请查收

helloworld1024fd

JavaScript

从react源码看hooks的原理

flyzz177

React

以开发之名 | 小红书:用年轻人的方式开发年轻人喜欢的应用

HarmonyOS SDK

视频超分 小红书

安装和体验hive

程序员欣宸

hadoop hive 11月月更

react高频知识点梳理

beifeng1996

React

华为云从入门到实战 | 负载均衡服务原理

TiAmo

华为 华为云 10月月更

Vue.$nextTick的原理是什么-vue面试进阶

bb_xiaxia1998

Vue

看透react源码之感受react的进化

goClient1992

React

从recat源码角度看setState流程

flyzz177

React

react的useState源码分析

flyzz177

React

高频js手写题之实现数组扁平化、深拷贝、总线模式

helloworld1024fd

JavaScript

如何用 JavaScript 编写你的第一个单元测试

茶无味的一天

JavaScript 单元测试 mocha

面试官:说说Event Loop事件循环、微任务、宏任务

loveX001

JavaScript

聊一聊责任链模式

设计模式 责任链模式

React源码分析(一)Fiber

goClient1992

React

探究Presto SQL引擎(4)-统计计数

vivo互联网技术

浏览器 presto 引擎

字节前端面试被问到的react问题

beifeng1996

React

React-hooks面试考察知识点汇总

beifeng1996

React

Docker不香吗?为什么还要用k8s

源字节1号

微信小程序 软件开发 前端开发 后端开发

左耳朵耗子:我对GitLab误删除数据库事件的几点思考_数据库_陈皓_InfoQ精选文章