前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >我从10次停机中学到的几个经验

我从10次停机中学到的几个经验

作者头像
深度学习与Python
发布于 2023-04-01 08:15:52
发布于 2023-04-01 08:15:52
7850
举报

作者 | Tom Kleinpeter and Jamie Turner

译者 | 王强

策划 | 万佳

1宕机事件总结

本文总结了过去遇到的许多次宕机事件中反复出现的问题。工程团队在处理这些事件时,某些模式(无论是作为风险还是作为资产)几乎次次都能遇到。

从这些反复出现的模式中,我们提取出了一些工程团队准备采纳的经验教训,希望你也能从中学到有用的知识并做好准备。

2第 1 课:循环依赖会破坏你的运维工具

使用自己做出来的东西是一种很好的做法——毕竟,如果你都不这样做,你怎么能指望客户使用你的产品和服务呢?如果你不拿自己公司的生产力当作赌注,如何为这些产品和服务实现的流程背书呢?

但这种健康的习惯也会产生反作用,因为这种行为会造成依赖循环。所谓依赖循环是说,你依赖自己的系统……来修复你的系统。

这种依赖模式还有其他一些实例,它们都违背了一条座右铭:不要重复自己。为什么只为了监控用途就要再运行一种数据库?你的生产数据库本来运行得很好,所以把遥测数据也放在那里就行了。

这些循环也会在停机期间带来严重后果。例如,你可能需要身份验证才能访问操作系统,修复身份验证模块……或者监控本来应该正常运行的数据库以获取指标数据,找出数据库出了什么问题。总之就是这样的死循环。

甚至客户通信系统有时也会损坏,因为你用了自己的系统将系统状态传递给客户。

 引文

  • 第 1 集,Slack 与 TGW:Slack 无法访问控制面板来了解他们的系统出了什么问题,因为 AWS Transit Gateway 需要处于健康状态才能将 http 流量传输到控制面板上。不幸的是,这个 TGW 是不健康的。
  • 第 3 集,Monzo 的 2019 年 Cassandra 宕机:Monzo 的生产数据库出现故障,要验证系统访问权限和部署代码才能解决问题,但前者必须使用这个生产数据库。
  • 第 10 集,Kinesis 达到线程限制:AWS 无法更新 Kinesis 相关中断的状态页面,因为状态页面的更新依赖 Kinesis。
  • 第 11 集,Salesforce 发布了有争议的事后分析:Salesforce 无法更新他们的状态页面,因为他们将其托管在基于 Heroku 的服务上,并且由于 Heroku 就是他们所有的,还集成到了他们的基础设施中,所以 Heroku 的运行状态取决于他们的系统健康状况。

3第 2 课:愚蠢的自动化

大家都对现代公有云及其提供的无数 API 感到非常兴奋。弹性!编排!所有运维都可以自动化,这样人类就不会被吵醒了!

但是这种热情有时会让我们过度自动化系统,进而很难测试退化的用例。而且这些未经测试的退化用例可能会有很大的不利影响,相比之下,在健康的系统状态下,实现自动决策带来的那点效率或经济优势是不够看的。

但即使自动化确实是明智的(因为系统需要经常调整,和 / 或调整所涉及的经济成本较大),自动化有时也缺乏必要的“恐慌模式”,无法识别参数何时超出正常范围。在这些情况下,自动化应该停止自动化操作并通知运维人员,因为它即将开始做出一些非常不合逻辑的决定了。

 引文

  • 第 1 集,Slack 与 TGW:由于出现一个网络问题期间 CPU 闲置,Slack 的自动化操作丢弃了一堆他们“不需要”(旁白:可他们确实需要)的服务器,然后在流量激增时启动了过多的服务器,超出了系统上的文件描述符限制。
  • 第 6 集,GitHub 的 43 秒网络分区:GitHub 的数据库自动化在一次为时 43 秒的网络分区期间,对一个主数据库进行了记录不完整的跨国提升。
  • 第 8 集,Auth0 的严重拥塞的数据库:当请求因数据库瓶颈而变慢时,Auth0 启动了两倍的前端,结果带来了更大流量,让问题更严重了。

4第 3 课:现在是 2021 年,数据库仍然很棘手

如果一切都是无状态的,那会怎样呢?那些讨厌的数据库总是给我们找麻烦。甚至在前端层表现出来的问题也常常是上游数据库引发的堵塞,源头可以追溯到深层服务栈的瓶颈。

这个主题的素材非常丰富,我们把它分解成三个子课程:

 第 3a 课:生产数据库应该主要是点查询或严格限制的范围

生产系统喜欢平坦、均匀且差异小的负载。对数据库服务器来说,它们喜欢许多非常快速的查询,可能都是有索引支持的,这样最坏情况下成本也是可以控制的。

为确保这一点,请将你的任意批量查询放在专用的辅助服务器中,或者放在一些 OLAP 系统(如 BigQuery 或 Snowflake)中。或者转储到 CSV 和并行 grep 都可以。不管这些批量查询复杂程度如何,是不是符合你的数据集大小和流程,都请这样做。

而且,如果你对查询时间分布还不够了解,无法知道尾部是否有疯狂的表扫描,请立即添加相应的监控。

 引文

  • 第 2 集,Gitlab 的 2017 年 Postgres 停机:非常昂贵的、长时间运行的帐户删除操作被放在了他们的生产数据库上实时运行,导致拥塞和故障。
  • 第 5 集,Auth0 悄悄丢失了一些索引:创建索引时未受监控的失败导致一些查询突然变成扫描,从而大大增加了数据库的负载并最终导致停机。
  • 第 8 集,Auth0 的严重拥塞的数据库:生产系统上发生的一些特别昂贵的扫描加剧了数据库问题。

 第 3b 课:避免数据库中的“中间魔法”

什么是中间魔法?我们来大致了解一下。

好选项:使用像 MySQL 这样的无聊事物并自己处理分片。这会很麻烦,因为你必须在应用层做很多额外工作,但当它崩溃时你可能会知道它是如何运作的。这在 10 年前可能是正确的想法,但现在看来也不错。

更好的选项:只需购买一个更大的服务器并使用一个未分片的 MySQL/PostgreSQL 服务器和一个或两个副本。这种办法一直都是好方案,尽可能选择它。

可能是 2021 年后最好的选项:花钱找云服务提供商为你运行数据库,包括所有备份和故障转移等业务。如果你真的喜欢,你甚至可以使用很帅气的数据库,例如 CloudSpanner、DynamoDB 之类。完全、不透明地依赖第三方在过去是不可想象的,但这可能是 2021 年最好的办法。这些大公司在这方面做得非常好,毕竟他们做得不好的话,因为你的公司就是依赖他们运营的,估计你们已经完蛋了。缺点是它会让你破费多多,因为这些服务的定价很高。

玩火选项:使用一些声称可以自动解决所有扩展和故障转移问题的东西,但你仍然需要做运维工作,而且它的生产环境历史比 MySQL 之类的东西少得多。当它出错时,很少有人知道如何操作,或充分了解其内部结构以诊断其编排流程的复杂故障模式。我们在这些停机事件中遇到的可能嫌疑人包括 MongoDB 和 Cassandra。

 引文

  • 第 3 集,Monzo 的 2019 年 Cassandra 停机:扩展的 Cassandra 集群有很多难以理解的配置麻烦。
  • 第 5 集,Auth0 悄悄丢失了一些索引:在不降低实时流量的情况下,在 mongo 中重新同步副本是很难实现的。

 第 3c 课:重点在于恢复而不是备份,还要注意它们需要多长时间

如果你不能证明你可以恢复某项内容,那么备份就没有任何意义。并且你还要恢复到正确的记录上,恢复需要的时间太久也不行。

让我们来看看有哪些情况:

  • 备份没有运行……这怎么可能,我明明正在监控它啊!
  • 备份在 S3 中运行并生成了一个文件。这可能要看你的备份验证到了什么地步。可能的情况是该文件为空,或者它包含的唯一有用的字符串是:Error: permission denied on directory /data。你的公司完蛋了。
  • 备份表面上包含大量重要数据,但在上传时已损坏。你的公司完蛋了。
  • 备份包含有效的数据库!但是由于备份脚本中的循环错误,每个分片都是分片 0。你公司的 87.5% 已经消失了。
  • 每个备份都包含正确、有效的数据库!但是你只能通过一个 85 毫秒的链接从廉价的存储类下载它,意味着恢复需要 2 周时间。你的公司还是没了。

因此,请一定要证明你的恢复是有效的——自动化并监控这一步骤,不要只是偶尔做一次验证——并确保它们会在可接受的时间内恢复完成。4 小时的宕机会是糟糕的一天,但 4 天的宕机后,你的公司就完蛋了。确保你的公司政策可以容忍这样的恢复时间,并让你的领导签字,这样当工程团队在灾难期间需要 7 小时才能恢复数据库时,他们也不会抓狂。

 引文

  • 第 2 集,Gitlab 的 2017 年 Postgres 停机:备份脚本每天都在运行,将内容放到 S3 中……直到软件更新破坏了备份脚本。对应的修复还没有真正经过测试。
  • 第 6 集,GitHub 的 43 秒网络分区:恢复需要很长时间(10 小时以上),尤其是在流量高峰期间,导致站点退化了很长时间。

5第 4 课:分阶段慢慢部署

尽管我们尽了最大努力,错误仍然会发生。我们会引入错误、或错误配置的东西、或传播错误的防火墙规则,或其他什么事物。

但分阶段部署可以把问题锁定在确定的范围内,因此你可以在火势蔓延并烧毁整个站点之前先看到哪里在冒烟。

我们讨论过的许多团队都有一套周密的部署方法,以确保他们公司的员工是第一批尝试其服务更改的用户,然后只有一小部分客户会提前试用新的部署。

下面是一个具体的例子:

  • 部署到你的 Dogfooding(自家用)集群——每小时或每个更改集,当前的 HEAD 版本都会部署给你的员工。这可以让你自己的团队在客户发现问题之前未雨绸缪。
  • 金丝雀 集群——按照你的发布节奏(也许每天一次?),发布候选被推送到一个小型部署,将它暴露给你的一小部分用户。一些公司会从几十个数据中心里挑一个来做金丝雀;其他公司根据他们的 user_id 或类似的东西挑出用户群的一部分来部署。发布经理可能会仔细监控金丝雀受众中这个新版本的对应指标,然后再继续……
  • 生产。现在它开始走向更广阔的世界。根据服务的重要性和发布节奏,有时生产部署会同时进行,有时会进一步分批部署,比如一次部署一个数据中心。

对于采用这些方法的公司来说,一些小问题往往不会被大多数用户发现,因为它被自用、金丝雀或其他阶段提前捕获了。

而在公司没有使用分阶段部署的情况下,事情显然不太顺利……编写事后分析的团队往往是第一个指出分阶段部署会有多大影响的团队。

 引文

  • 第 4 集,一个微妙的正则表达式让 Cloudflare 瘫痪:Cloudflare 非常快速地部署了一种更昂贵的基于正则表达式的规则,结果由于 CPU 耗尽而导致整个站点瘫痪
  • 第 11 集,Salesforce 发布了一个有争议的事后分析:一个 DNS 配置更改的快速部署让他们的所有名称服务器都下线了。

6第 5 课:为失败做好准备,提前写好策略和计划

最后,虽然我们都愿意相信,如果测试非常彻底,并且周到地安排了所有事情,我们将不会再遇到大规模宕机事故……可我们都知道它们仍然会迟早发生。

因此,正如从许多停机事件中了解到的那样,如果在停机之前就把策略和计划内置到我们的系统和剧本中,我们就更容易从这些事件中恢复了。

策略意味着经过深思熟虑并做出决定,例如:如果整个站点因超载而停机,我们首先要减少哪些流量来恢复正常?这些流量涉及什么类型或什么类别的客户?如果这些决定是提前做出的,并由领导签字,甚至可能得到律师的验证,工程团队就更容易把压力减到阈值以下。

计划是说:我们可以设置类似“恐慌模式”之类的东西,在这种模式下编排会停止、负载均衡器变得不那么聪明,并且非必要的工作会自动暂停。我们可以有一个运行时参数,调整它可以减少一点负载,这样我们就不必关闭和打开所有东西,惊动一大堆客户了。

 引文

  • 第 1 集,Slack 与 TGW:Slack 使用了特使代理的恐慌模式,让负载平衡算法在过载时找到健康主机的机会大大增加。
  • 第 4 集,一个微妙的正则表达式摧毁了 Cloudflare:Cloudflare 已经制定了政策和支持使用条款,允许他们在服务出现故障时关闭全球 Web 应用程序防火墙。此外,他们有一个运行时参数,允许他们无需部署代码就能立即禁用它。
  • 第 6 集,GitHub 的 43 秒网络分区:GitHub 在从过载中恢复时关闭了 Webhook 调用和 GitHubPages 构建。
  • 第 9 集,Coinbase 惊动了大批客户:在 Coinbase 需要配置自己的一个集群,结果在关闭 / 打开所有流量后惊动了大批客户,他们本应该缓慢恢复流量的。

7小结

在回顾了所有这些压力巨大的宕机事件后,我们得出了一个非常令人鼓舞的结论:包括我们在上面列举的许多实践在内,一些常见实践可以预防或显著减轻各种站点停机问题带来的严重影响。

原文链接:

https://downtimeproject.com/podcast/7-lessons-from-10-outages/

本周好文推荐

有钱没人!人才短缺将成云计算快速发展的致命弱点

我的开源代码被科技巨头偷了,对方还跑到我面前演示

七部委进驻滴滴;活久见!腾讯阿里讲和;京东宣布全员涨薪两个月;IPIP.net状告阿里云 | Q资讯

CentOS 8退役倒计时,开发者们又吵起来了


InfoQ 写作平台欢迎所有热爱技术、热爱创作、热爱分享的内容创作者入驻!

还有更多超值活动等你来!

扫描下方二维码

填写申请,成为作者

开启你的创作之路吧~

点个在看少个 bug 👇

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 InfoQ 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Flask框架(五)之SQLAlchemy
SQLAlchemy是一个基于Python实现的ORM框架。该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
GH
2020/03/19
3K0
SQLAlchemy
SQLAlchemy是一个基于Python实现的ORM框架。该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
小小咸鱼YwY
2020/06/19
3.2K0
Flask使用SQLAlchemy连接mysql
表操作 models.py from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column from sqlalchemy import Integer,String,Text,Date,DateTime from sqlalchemy import create_engine Base = declarative_base() class Users(Base): __tablenam
人生不如戏
2018/06/21
1.7K0
SQLAlchemy SQLAlchemy
SQLAlchemy 1.1.SQLAlchemy介绍 SQLAlchemy是一个基于Python实现的ORM框架。该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用数据API执行SQL并获取执行结果。 安装 pip install sqlalchemy 组成部分 Engine,框架的引擎 Connection Pooling ,数据库连接池 Dialect,选择连接数据库的DB API种类 Schema/Types,架构和类型 SQL Exprr
zhang_derek
2018/05/30
2.3K0
SQLALchemy的其他常用操作
使用连接池的两种方式 第一种方式: 直接从SessionFactory里获取,此时如果需要开启多个进程,那么创建连接池的代码一定要放在循环里面 不然的话每个进程都是用一个session了 from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from models import Student,Course,Student2Course engine = create_engine( "my
人生不如戏
2018/07/05
7870
Python操作MySQL(二) ORM
SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
py3study
2020/01/06
1.5K0
Python操作MySQL(二) ORM
pymysql
pymsql是python中操作的MYsql的模块,其使用方法和MySQLdb几乎相同
Wyc
2018/09/11
4.2K0
pymysql
python_day11のPython操
pymysql是Python中操作MySQL的模块,其使用方法和python2.7的MySQLdb几乎相同。
py3study
2020/01/13
4730
STM32 通过外部时钟输入模式测量频率,串口打印
使用了stm32f103zet6 通过外部时钟输入模式进行频率采集,在100khz以上误差在10hz左右
用户4585225
2020/12/17
2.2K0
python ORM框架SQLAlchemy
SQLAlchemy是一个基于Python的ORM框架。该框架是建立在DB-API之上,使用关系对象映射进行数据库操作。
用户5760343
2022/05/14
7660
ORM框架SQLAlchemy
原文链接:https://www.cnblogs.com/mengqingjian/articles/8521512.html
菲宇
2019/09/23
1.2K0
ORM框架SQLAlchemy
Python SQLAlchemy入门教程
本文将以Mysql举例,介绍sqlalchemy的基本用法。其中,Python版本为2.7,sqlalchemy版本为1.1.6。
oYabea
2020/09/07
3.3K0
Python操作SQLAlchemy
SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
菲宇
2019/06/13
8620
Python操作SQLAlchemy
SQLAlchemy总结+
Review: 一、Mysql 操作 创建一个test库 create database test; 授权一个用户 grant all privileges on *.* to 'asd'@'%' identified by 'awerfsdf123'; 创建表 create table student(id int not null); 查询 select * from tabel_name where 条件1 and 条件2 增加 insert into table_name (id, name
老七Linux
2018/05/31
2.3K0
Python 学习笔记 - SQLAlc
例1. 获取主机1的所有用户,原理和1对多的一样,通过relationship快速定位到对应的表
py3study
2020/01/15
3260
Python 学习笔记 - SQLAlc
Python ORM - pymysql&sqlalchemy
Python3主要是面向对象的编码风格,访问数据库也可以使用ORM框架来实现面向对象,本文介绍pymysql和sqlalchemy 安装组件 pip3 install pymysql pip3 install sqlalchemy 定义数据对象 user表结构 CREATE TABLE `user` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL, `age` int DEFAULT NULL, `del
十毛
2021/01/21
7470
盘点Flask与数据库的交互插件--Flask-Sqlalchemy
在我们做web开发的时候,经常需要用到与数据库交互,因为我们的数据通常都是保存在数据库中的,如果有人需要访问,就必须与数据库访问,所以今天我们介绍一个Flask中与数据库交互的插件---Flask-Sqlalchemy。
Python进阶者
2021/08/20
2.5K0
使用Python操作MySQL和Oracle数据库
前面两篇文章已经说过将数据存储到SQLite和本地文件中,如果还没有来得及看,可点击如下快速链接:
JiekeXu之路
2019/08/15
2.9K0
Python 数据库操作 SQLAlchemy
在运行过程中所有的的数据都存储在内存 (RAM) 中,「RAM 是易失性存储器,系统掉电后 RAM 中的所有数据将全部丢失」。在大多数情况下我们希望程序运行中产生的数据能够长久的保存,此时我们就需要将数据保存到磁盘上,无论是保存到本地磁盘,还是通过网络保存到服务器上,最终都会将数据写入磁盘文件。将数据保存在磁盘中我们需要面对一个数据格式的问题,此时就需要引入数据库操作。
keinYe
2019/08/01
1.6K0
SQLAlchemy学习-9.一对多和多对一关系
前言 一对多和多对一关系 一对多关系 一对多关系表设计,一个Parent类关联多个Child类 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine, Column, Integer, String, ForeignKey from sqlalchemy.orm import relationship # 拼接配置dialect + driver://username:pa
上海-悠悠
2022/08/26
3.3K0
SQLAlchemy学习-9.一对多和多对一关系
相关推荐
Flask框架(五)之SQLAlchemy
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文