大模型“四虎”出山,亮相 4 月 QCon 北京。 了解详情
写点什么

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

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

关注

评论

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

辞旧岁立新年 | 展望前端工程师的2023

字节跳动终端技术

云原生 前端 前端工程师

模型推理耗时降低98%!PaddleTS又双叒叕带来重磅升级!

飞桨PaddlePaddle

paddle

Apipost参数描述的填写和参数描述库的使用

爱研究代码的极客人

Postman 参数 参数定义 apipost

在线研讨会邀请 | 赋能“大”研发,助力“快”交付

龙智—DevSecOps解决方案

版本控制 线上研讨会 研讨会 数字资产管理

云安全之浅谈密钥泄露

HummerCloud

云安全 密钥

【SOP】新扩容节点与集群版本不一致处理

TiDB 社区干货传送门

实践案例 版本升级 管理与运维 故障排查/诊断 扩/缩容

Apipost如何快速生成并分享API实时文档

popo223344

后端

云数据库 TiDB试用

TiDB 社区干货传送门

ITSM | 限时优惠,帮助您的团队终结不良服务管理!

龙智—DevSecOps解决方案

Jira ITSM IT服务管理

大型集团企业数据治理实践,推进全域数据资产体系建设 | 数字化标杆

袋鼠云数栈

神锁离线版和Bitwarden的自动填充:超级英雄 vs 被斗转星移的瞎鸟

神锁离线版

密码管理 密码管理器 密码安全 Bitwarden 神锁离线版

软件测试/测试开发 | App自动化之dom结构和元素定位方式(包含滑动列表定位)

测试人

软件测试 自动化测试 测试开发

迈铸半导体完成1500万Pre A+轮融资,用于实现规模化量产

硬科技星球

MASA Stack 1.0 发布会讲稿——实践篇

MASA技术团队

.net MASA MAUI MASA Stack

七年的开源商业化探索,PingCAP 为什么选了这样一条路?

TiDB 社区干货传送门

数据库前沿趋势

代码质量与安全 | 开发人员必备的安全编码实践指南

龙智—DevSecOps解决方案

代码安全 静态代码扫描

龙智宣布与Incredibuild建立战略合作伙伴关系

龙智—DevSecOps解决方案

DevSecOps 加速编译

java核心技术-多线程基础

蓦然

Spring Java

云数据库 TiDB 体验——部分故障问题与解决方法

TiDB 社区干货传送门

版本测评 新版本/特性解读 6.x 实践

【2.3-2.10】写作社区优秀技术博文一览

InfoQ写作社区官方

热门活动 优质创作周报

云数据库 TiDB 试用实践——部署&运维

TiDB 社区干货传送门

版本测评

PingCAP黄东旭:Serverless是数据库的未来形态

TiDB 社区干货传送门

数据库前沿趋势

br备份时排除某个库

TiDB 社区干货传送门

实践案例 备份 & 恢复

2023最好用的10个开发者工具!每一个都让你效率翻倍

popo223344

工具 测试 后端

剖析字节案例,火山引擎A/B测试DataTester如何“嵌入”技术研发流程

字节跳动数据平台

大数据 AB testing实战 企业号 2 月 PK 榜

海外多语言数字货币交易app系统开发搭建

开发微hkkf5566

TiKV RocksDB读写原理整理

TiDB 社区干货传送门

TiDB 底层架构 TiKV 底层架构

# 文盘Rust -- rust 连接云上数仓 starwift

TiDB 社区干货传送门

开发语言

选择等保测评机构需要注意的几个点-行云管家

行云管家

等保 等级保护 等保测评

云原生场景下,如何缓减容器隔离漏洞,监控内核关键路径?

OpenCloudOS

Linux 云原生 服务器

架构实战营第 10 期 - 模块六:拆分电商为微服务

kaizen

「架构实战营」

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