NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

Airbnb 是如何在两周内完成数据库切分的

  • 2015-11-03
  • 本文字数:4292 字

    阅读完需:约 14 分钟

【编者的话】
Airbnb 是一家联系旅游人士和家有空房出租的房主的服务型网站,其总部位于美国旧金山。Airbnb 可以为用户提供各式各样的住宿信息。2011 年,Airbnb 服务难以置信地增长了 800%。用户数量的不断增加必将导致 Airbnb 用户数据量的激增,从而为数据的存储带来了巨大的压力。

数据量的猛增首先必然要求增加数据存储空间,同时还对数据存储的可扩展性和稳定性提出很高的要求。如何来解决这个问题呢?针对这个问题,Airbnb 提出了一个非常有影响力的项目,旨在通过应用函数将特定的表格进行划分,存储在不同的数据库中。这通常需要做很多工程上的投资,主要涉及到应用层的改变、数据迁移和可靠性测试,目的是通过最少的停机时间确保数据的一致性。

具体来说,Airbnb 又是如何实现的?Airbnb 的工程师 Willie Yao 在其博客中分享了他们的具体工作,以及他们在这个过程中所学习到的一些东西。本文是一篇翻译稿,原文题目为“ How We Partitioned Airbnb’s Main Database in Two Weeks ”。

正文

“扩展等于给运行在 100km/h 的高速汽车更换所有部件。”

——Mike Krieger,Instagram 的联合创始人 @ Airbnb OpenAir 2015

Airbnb 住宿高峰以每年 3.5 倍的速度增长,而且都在夏季达到最高峰。

每当进入夏季,Airbnb 都会迎来一个住宿的旺季,正如上图所示,而且住宿高峰还以每年 3.5 倍的速度在增长。开始进入 2015 年夏季旅游旺季的时候,Airbnb 的基础架构团队就一直在努力扩展我们的数据库,以应对夏季高峰期高的访问流量。一个尤其有影响力的项目旨在通过应用函数将特定的表格进行划分,存储在不同的数据库中。这通常需要做很多工程上的投资,主要涉及到应用层的改变、数据迁移和可靠性测试,从而通过最少的停机时间确保数据的一致性。在整个项目的攻坚过程中,我们中一位非常优秀的工程师提出了一种非常有趣的想法,即利用 MySQL 复制来应对数据一致性中的最困难的那一部分。 (这个想法来自于亚马逊 RDS 的“Read Replica Promotion”功能的一个明确用例)在数据库升级过程中通过容忍一个短暂和有限的停机时间,我们能够执行此操作,而无需编写任何一行bookkeeping 或migration 代码。在这篇博客中,我们将分享我们的一些工作,以及在这个过程中所学习到的一些东西。

首先,一些背景

我们在 Asana Percona 的朋友认为水平分片并不是很好的解决方法,我们倾向于同意他们的观点,所以我们选择通过应用函数进行垂直划分以传播负载和隔离故障。例如,我们有专门的数据库,每个都运行着他们各自的 RDS 实例,它们与我们独立的 Java 和 Rails 服务形成一对一的映射。但是由于历史原因,很多我们的核心应用数据仍然存储在原始的数据库中,因为早前 Airbnb 只是一个单一的单片 Rails 应用程序。

利用我们内置的客户端查询分析器来分析我们的数据库访问模式,我们发现 Airbnb 让客人与主机进行通信的消息收件箱功能,在我们的主数据库中占据了将近 1/3 的写入。此外,这种写入模式还会与流量线性增长,所以将其划分出来对于提高我们的主数据库的稳定性将是一个巨大的成功。因为它是一个独立的应用功能。同时,我们也有信心,所有跨表的连接和事物都可以被排除,所以我们优先开始了这个项目。

在研究这个项目的过程中,两个现实问题影响到了我们的决策。首先,我们最后一次划分数据库已经是三年前,所以在当前的规模下,继续采取这种操作对我们来说是一个新的挑战,我们付出了计划停机时间的代价,只为最大限度地减少工程的复杂性。其次,当我们进入 2015 年之后,公司大约有 130 名软件工程师,我们的团队在很多领域拓宽了自己的产品,从个性化搜索、客户服务工具、信任和安全、全球支付,到可靠的移动应用程序,这些工作占用了公司很大一部分工程力量,相反只留下很小部分工程用于基础架构的建设。考虑到这些因素,我们选择使用 MySQL 复制,以尽量减少工程的复杂性和需要的投资。

我们的计划

对我们来说,决定使用 MySQL 内置的复制功能进行数据迁移意味着我们不需要再单独打造最具挑战性的部分来确保数据的一致性,因为复制已经被证明是一种成熟的方式。我们在 Amazon RDS 上运行 MySQL,因此创建新的读出副本以及转移一个副本到 standalone 主机上是容易的。我们的环境集成了下面这些部分:

我们从我们的 main master 数据库中创建了一个新的副本(消息 master),消息 master 在升级之后可以作为一个新的独立的主机工作。然后,我们连接一个第二层副本(消息副本,message-replica),其可以作为消息 master 的副本工作。美中不足的是,升级过程可能需要几分钟或更长的时间才能完成,在此期间,我们必须放弃对相关表格的写入操作,以保持数据的一致性。鉴于一个不堪重负的数据库带来的超长的停机时间会比一个本地化的、受控的消息收件箱的停机时间要长得多,我们的团队愿意作出妥协。值得一提的是,对于那些运行自己的数据库的人,复制过滤器能被用来避免复制不相关的表格,潜在地减少了升级的时间。

第一阶段:预规划

迁移消息收件箱中的表格到一个新的数据库中可能使使用跨表连接的现有查询在迁移之后失效。因为数据库升级后无法恢复。幸运的是,我们的内部查询分析器允许我们很容易地识别对大部分主要的服务的查询,我们能够撤销对剩余服务的相关数据库的权限授予,以获得完全的覆盖。在 Airbnb 工作的其中一个原则是服务应该拥有自己的数据,这将极大地简化了这里的工作。虽然在技术上简单明了,这却是工程中最耗时的一个阶段,因为它需要良好的跨团队沟通能力。

接下来,我们有一个非常广的数据通道能够提高离线数据的分析能力和下游产品的服务能力。所以预规划的下一步是迁移我们所有相关的通道来占用消息副本的数据出口,以确保升级之后使用的是最新的数据。这个迁移计划也存在一个不足,即使升级之后数据分开了,新的数据库与我们现有的数据库还是具有相同的名字(使用我们的 RDS 实例的名称并不会混淆,如 message-master 和 message-replica))。然而,这实际上允许我们在数据通道中保持命名规则的一致,所以我们选择不对数据库进行重命名。

最后,因为我们主要的 Airbnb Rails 应用程序采用独占的方法对这些表格进行写入访问,我们能够交换所有相关的服务流量到新的消息数据库副本中,用来减少主操作的复杂性。

第二阶段:操作

一旦所有预规划工作已经完成,实际的操作按以下步骤执行:

  1. 与我们的客户服务团队沟通,计划收件箱中的停机时间在 10 分钟以内。对一个事实我们非常敏感,即当客户正试图 check in 到自己的 Airbnb 账号的时候,任何停机都可能让客人滞留在国外,所以让所有的相关功能一直运行,然后执行这些操作在访问并不繁忙的时候是非常重要的。
  2. 对消息收件箱中的查询变更为使用新的消息数据库用户授权和数据库连接进行部署。在这个阶段,在读出数据到消息副本的时候,我们仍然可以对 main master 进行写入,同时读取到的信息复制,所以这对外应该没有影响。然而,我们推迟这一步,直到操作开始,因为它是需要两倍于对主机的连接,所以我们希望这个阶段尽量简单。下一步,交换数据库主机不需要这个部署,因为我们在 Zookeeper 上有配置工具来更新数据库主机条目,在那里它们可以通过 SmartStack 被发现。
  3. 交换所有消息收件箱写入流量到消息主机。因为它还没有被升级,在新主机上的所有的写入操作都会失败,此时也开始对停机时间进行计时。然而读出请求是成功的,实际上几乎所有的消息传输在这个阶段都会慢下来,因为读出时标记一个消息需要一个数据库写入操作。
  4. 切断所有 main master 与消息数据库的数据库连接。不需要执行一个部署或进行集群重启,只需要直接切断连接,我们尽量减少所有写入副本的时间,这个副本将作为一个新的主机工作。
  5. 通过检查下面各项验证复制已经被赶上:
  • 在消息 master 和消息副本上所有消息收件箱中的表格的最新条目
  • main master 上的所有消息连接都没有了
  • 消息 master 上的新连接都建立起来了
  1. 升级消息 master。根据我们的经验,在 RDS 上进行升级的过程中,该数据库完全停下来大约需要 30 秒,在这段时间里,master 上的读出操作失效。然而,写入将失效将近 4 分钟,因为在升级计时之前,需要花费大约 3.5 分钟,然后它才启动。
  2. 在下一次 RDS 自动备份窗口之前,在最新升级的消息 master 上启用 Multi-AZ 部署。除了提升对失效转移的支持,Multi-AZ 最大程度地缩短了 RDS 快照和备份的延迟高峰。
  3. 一旦所有的指标看起来不错,以及数据库也稳定,丢弃各自的数据库中不相关的表格。这最后一步很重要,因为可以确保没有服务使用了陈旧的数据。

如若操作失败,我们将恢复 Zookeeper 上的数据库主机条目,消息收件箱功能也将被立即恢复。然而,任何写入的东西将丢失。理论上,恢复并回填丢失的消息是可能的,但是这将耗费很大的力气和并让用户感觉混乱。因此,在继续操作之前我们会非常仔细地检测了上述各步骤。

结果

主数据库的主机写入明显下降。

端对端的部署,这个项目花了大约两个星期才完成,消息收件箱中的停机时间仅仅只有 7 分半钟,我们的主要数据库的大小减小了 20%。最显著的是,通过将我们的主要的主机数据库上的写入查询降低 33%,这个项目显著提高了数据库的稳定性。这些迁移的查询预计在未来数月内将另有 50%的增长,这肯定会给我们的主数据库造成非常的负担,所以这个项目花了我们很多的宝贵时间,主要为了追求数据库长期的稳定性和可扩展性。

一个惊喜:RDS 快照会显著提高延迟

按照 RDS 文档

不同于 Single-AZ 部署,在为 MySQL、Oracle 和 PostgreSQL 引擎进行 Multi-AZ 部署期间,I / O 活动并不会暂停,因为备份处于待机状态。但是,请注意,您仍然可以在为 Multi-AZ 部署的备份过程中体验到几分钟的延迟增加。

我们通常启动 RDS 所有主机实例上的 Multi-AZ 部署,以充分利用 RDS 的高可用性和对失效转移的支持。在这个项目中,我们观察到,给予一个足够的数据库负载,即使使用 Multi-AZ 部署,一个 RDS 快照所经历的延迟可能足够给我们造成查询的大量积压,并搞垮我们的数据库。我们意识到快照会导致延迟增加,但在此之前的项目中,我们没有意识到,延迟的非线性增加导致完全停机的概率是与数据库负载相关的。

显然,RDS 快照是 RDS 功能的核心,我们依赖于它每日进行自动备份。以前我们不知道的是,当我们的主数据库的负载增加时,RDS 快照引起站点不稳定的可能性也随之增加。因此,在完成这个项目中,我们认识到,项目比我们原先预计的更为迫切。


感谢徐川对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-11-03 18:013051
用户头像

发布了 268 篇内容, 共 118.2 次阅读, 收获喜欢 24 次。

关注

评论

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

react源码解析3.react源码架构

全栈潇晨

React React Hooks react源码

C 语言面向对象的封装方式

实力程序员

华为云携手马栏山文创园助力湖南广电荣获国家广电总局多项大奖

华为云开发者联盟

AI 5G 视频 华为云 马栏山

图表示学习+图神经网络:破解AI黑盒,揭示万物奥秘的钥匙!

博文视点Broadview

一封MySQL之父Monty的回信,开启彭立勋的数据库之路

华为云开发者联盟

MySQL 数据库 opengauss GaussDB 华为云数据库

架构实战营模块五作业

竹林七贤

总结笔记 Datawhale-23期数据挖掘-心跳信号分类预测

万里无云万里天

数据挖掘 6月日更 Datawhale

《面试官:谈谈你对索引的认知》系列之B+树

架构精进之路

MySQL 索引结构 6月日更

云网络开山之作,揭秘云上高速公路的十年技术成果!

博文视点Broadview

云上创新,阿里云视频云分享全场景音视频服务背后的场景探索与技术实践

阿里云视频云

阿里云 音视频 在线教育 视频会议 直播技术

基于开源Tars的动态负载均衡实践

vivo互联网技术

负载均衡 TARS

自适应微服务治理背后的算法

万俊峰Kevin

微服务 自适应 服务治理 Go 语言

fil云算力系统开发具体流程丨fil云算力开发源码成品

系统开发咨询1357O98O718

anyRTC SDK 5月迭代:优化自定义加密功能,让通信更安全

anyRTC开发者

音视频 WebRTC sdk

Rust从0到1-泛型-trait

rust 泛型 Trait generic

为什么说混合云是新基建的流行架构?

博文视点Broadview

书单 | 5月畅销新书情报,你最Pick哪一本?

博文视点Broadview

拉仇恨!webhook + 企业微信给同事做了个代码提交监听工具

程序员小富

Java GitHub 编程 程序员 代码

你的同事是你的竞争对手吗?

石云升

战略思考 职场经验 6月日更

带你认识大模型训练关键算法:分布式训练Allreduce算法

华为云开发者联盟

分布式训练 Allreduce算法 集合通信 分布式通信算法 大模型训练

LeaRun .Net Core/Java工作流引擎,分离式前端,升级Vue

雯雯写代码

Vue 工作流引擎

🏆未来可期,WebRTC成为实时通讯方案的行业标准

洛神灬殇

音视频 WebRTC 实时通信 6月日更

chia奇亚挖矿系统开发案例介绍丨chia奇亚挖矿源码功能

系统开发咨询1357O98O718

Flink+Alink,当大数据遇见机器学习!

博文视点Broadview

Chia奇亚云算力挖矿系统开发成功案例丨Chia奇亚挖矿源码成品

系统开发咨询1357O98O718

【Flutter 专题】115 图解自定义 View 之 Canvas (四) drawParagraph

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 6月日更

NQI质量基础设施“一站式”服务平台开发解决方案

源中瑞-龙先生

开发 解决方案 NQI 质量基础设施“一站式”

毕业设计So Easy:珠穆朗玛FM音频电台APP

不脱发的程序猿

android 软件开发 APP开发 毕业设计 移动应用开发

Spring Cloud Alibaba 实战

Damon

微服务 SpringCloud Alibaba 6月日更

火爆全网的迁移学习简明手册全面更新,重磅出版上市!

博文视点Broadview

国内首篇云厂商 Serverless 论文入选全球顶会:突发流量下,如何加速容器启动?

Serverless Devs

Serverless 容器 云原生

Airbnb是如何在两周内完成数据库切分的_数据库_张天雷_InfoQ精选文章