写点什么

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:013259
用户头像

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

关注

评论

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

8年Java开发含泪刷题,架构岗现在好难进,有点崩溃

钟奕礼

Java 程序员 java面试 java编程

2022年华为Java面经,还没搞懂JVM

钟奕礼

Java 程序员 Java 面试 java编程

赞不绝口!仅靠阿里P9分享的 Redis 工作手册,拿到60W年薪Offer

程序知音

Java 数据库 redis 后端技术 Redis 6.0

三到五年互联网公司Java面试题大全

钟奕礼

Java 程序员 java面试 java编程

CorelDraw2023主要功能特性

茶色酒

CorelDraw2023 CorelDraw

Java 后端 100多道面试题,多看点题,没坏处!

钟奕礼

Java 程序员 java面试 java编程

如何召回流失用户

穿过生命散发芬芳

11月月更 流失召回

这20道微服务面试题,阿里、字节、美团、百度面试都问了

钟奕礼

Java 程序员 java面试 java编程

CleanMyMac2023Mac系统电脑磁盘优化软件

茶色酒

CleanMyMac CleanMyMac2023

仅hashmap一道面试题我就搞定了面试官成功入职面试官:我裂开了

钟奕礼

Java java面试 java编程 程序员、

网络核心笔记(二)

lxmoe

学习笔记 网络 11月月更

亿级万物互联新时代的物联网消息中间件EMQX调研

宋小生

物联网 mqtt emqx

阿里、百度、美团、面试题大集合,愿你更轻松拿下大厂offer

钟奕礼

Java java面试 java编程 程序员、

霸榜巨作!阿里内部顶级大佬整理(Redis 5设计与源码分析)

钟奕礼

Java 程序员 java面试 java编程

Camtasia2023免费电脑录屏视频软件使用教程

茶色酒

Camtasia Camtasia2023

【Logback+Spring-Aop】实现全面生态化的全链路日志追踪系统服务插件「Logback-MDC篇」

洛神灬殇

log4j logback 全链路追踪 11月日更 MDC

Redis分布式锁剖析和几种客户端的实现

C++后台开发

redis 分布式 后端开发 C++开发

API渗透测试4个关键步骤

阿泽🧸

11月月更 API渗透测试

一文搞懂MySQL表字段类型长度的含义

闫同学

MySQL 数据库 11月月更

2022成功入职阿里:阿里的三套Java研发岗面试题总结(文末有答案)

钟奕礼

Java java面试 java编程 程序员、

GitHub标星75k,阿里15W字的Spring高级文档(全彩版),真的太香了

程序知音

Java spring ssm java架构 后端技术

算法题学习---链表的奇偶重排

桑榆

算法题 11月月更

集合工具类Collections指南,以及Comparable和Comparator排序详解

共饮一杯无

Java 集合 11月月更

Java中的String类常用方法

共饮一杯无

Java string 11月月更

2022全网最全最新Java面试题-独家内部教材

钟奕礼

Java 程序员 java面试 java编程

网络核心笔记(一)

lxmoe

学习笔记 网络 11月月更

FL Studio21最新版编曲DJ舞曲制作软件

茶色酒

FL Studio FL Studio 21

Python进阶(五十三)Flask Web开发实现将表单渲染成HTML

No Silver Bullet

Python flask web开发 11月月更

从基础到实战,阿里巴巴高并发系统设计全彩版手册限时开源

Java全栈架构师

程序员 面试 程序员人生 高并发 架构师

ABBYY FineReader16最新版PDF编辑器功能介绍

茶色酒

abbyy

LeetCode题解:783. 二叉搜索树节点最小距离,栈,JavaScript,详细注释

Lee Chen

JavaScript 算法 LeetCode

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