最新发布《数智时代的AI人才粮仓模型解读白皮书(2024版)》,立即领取! 了解详情
写点什么

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

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

关注

评论

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

吊打面试官!Java基础(面向对象,java入门自学书籍推荐

Java 程序员 后端

上线直接霸榜!阿里内网流传P8大牛的“满级”分布式架构笔记

Java 编程 程序员 架构

同样是程序员,本科学历凭什么就比专科学历更吃香?,mybatis常见面试题

Java 程序员 后端

听音乐不过瘾?自制一个音乐播放器!,java程序设计基础知识点第七章

Java 程序员 后端

三面阿里被挂,竟获内推名额,历经5面拿下口碑offer(Java后台)

Java 编程 程序员 架构 面试

图解Redis数据结构篇之压缩列表,java注解原理解析

Java 程序员 后端

四年的开发经验只去面试了蚂蚁金服,无忧一次过,自学linux视频教程推荐

Java 程序员 后端

团灭LeetCode!Alibaba技术官甩出的大师级算法宝典真的太香了!

Java 程序员 后端

同事问我MySQL怎么递归查询,我懵逼了(1),阿里java技术专家评级

Java 程序员 后端

同事问我MySQL怎么递归查询,我懵逼了,java面试简历百度云

Java 程序员 后端

听我讲完redo log、binlog原理,面试官老脸一红,rabbitmq集群同步原理

Java 程序员 后端

哟,我发现 Dubbo 这波优化好像不够彻底啊?,深入java虚拟机第四版百度网盘

Java 程序员 后端

社招三面阿里“落榜”,幸获内推名额,4面揽下美团offer

Java 架构 面试 后端

图解Redis:一套方案轻松搞定数据库与缓存数据不一致问题(1)

Java 程序员 后端

在外包公司从Java后端干到安卓开发,你醒醒吧!,阿里大师推荐的这份Java开发必读书单

Java 程序员 后端

同事临走时,给了我这份多线程and高并发(面试题,小米java面试几轮

Java 程序员 后端

听说Lombok的@Builder不好使?快来试试这个,rocketmq原理面试题

Java 程序员 后端

和程序员谈恋爱的7种体验,linux多线程面试题

Java 程序员 后端

哇塞!这是我见过的最牛逼的性能监控系统,集强大功能于一身

Java 程序员 后端

吃透阿里大佬整理的Java面试要点手册,成功五面进阿里(二本学历

Java 程序员 后端

太为难我了,阿里面试了7轮(5年经验,拿下P7岗offer)

Java 程序员 面试 后端

同程旅行基于 RocketMQ 高可用架构实践,mysql破解版百度云

Java 程序员 后端

五面阿里、三面美团、四面字节跳动,最终拿offer入职字节!

程序员 数据结构 面试 算法

国内顶级大牛整理:分布式消息中间件实践笔记+分布式核心原理解析

Java 程序员 后端

图解Redis:一套方案轻松搞定数据库与缓存数据不一致问题

Java 程序员 后端

在SQL SERVER中实现RSA加解密函数,java入门书籍推荐

Java 程序员 后端

吹爆!阿里高工甩出内部强推Redis全栈笔记,Github已获赞78

Java 程序员 后端

嘘,助你一臂之力,快来瞧瞧这份-Spring-面试小抄,百度语音识别接口java

Java 程序员 后端

四面美团开发岗,成功斩获offer,这份面经总结终结篇看完就是血赚

Java 程序员 后端

团队管理(二)-敏捷开发最佳团队协作管理平台,mysql入门很简单视频

Java 程序员 后端

图说线性表-搞懂链表从这篇文章开始,2021必看-Java高级面试题总结

Java 程序员 后端

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