转载

互联网时光机Timehop:每天5000用户到5.5万用户 DynamoDB起到了什么作用?

文/Kevin Cantwell,Timehop首席架构师

2,675,812,470—— 这是Timehop最大表的行数。准确的说,这是去年互联网“时光机”Timehop最大表格的行数。截止目前,这个数字已经飙升至600亿行。初略计算,平均每天发生1.6亿次写入操作。

如果认真思考这个数字,它已经大到了令人头疼。但是因为我们使用的是Amazon的DynamoDB,这个数字基本上不需要任何关心。感谢DynamoDB,在Timehop注册用户高速增长时(从每天5000用户跨越到每天5.5万用户)充当了我们坚不可摧的后盾。

DynamoDB是什么?

本文,我并不打算去介绍DynamoDB的来龙去脉,或者DynamoDB是用来干什么的,因为在网上你可以发现很多介绍 DynamoDB文档 。我要说的是其最大的亮点:DynamoDB是个一致的、快速的、可以无限扩展的数据库。同时,这个无限扩展绝不是夸大其词,正如字面意思一样,数据库扩展过程中用户不会受到任何限制。当然这也并不是说任何规模下,DynamoDB的特性都有相同的表现,但是在一致性和速度方面确实不需要任何担心。在下文,我们会详细介绍这点。首先,进入看一下背景。

曾几何时,MongoDB让我操碎了心

当下,Timehop使用DynamoDB作为主要数据存储,每个历史tweet、照片、登陆以及状态都会形成时间序列数据持久化到DynamoDB。当然,在开始时我们使用的并不是DynamoDB,而是PostgreSQL和MongoDB的组合。那么,为什么要转换?

首先,MongoDB确实不错。我的意思是,我承认MongoDB确实是个不错的数据库。也就是说,许多人在MongDB上确实如鱼得水。然而,在大规模下场景下,MongoDB绝对不是我的菜。

互联网时光机Timehop:每天5000用户到5.5万用户 DynamoDB起到了什么作用?

在小规模下,MongoDB的使用非常顺心。我们不需要费尽心思去考虑所储存的文档,同时索引的使用也没有那么痛苦。但是,当我们达到2TB的规模时,我们在延时上看到严重且不可预知的峰值。现在来看,这可能由当时所选择的托管提供商所造成,与MongoDB本身无关(在那个时候,我们使用了Heroku上的一个托管服务)。或者这么说,如果我们使用自己的主机,通过分片可能就会解决这个问题。但是老实说,Timehop并没有专业的DBA,因此租用数据库服务显然更适合我们(只要开销不爆表!)。这样一来,我们开始寻找替代方案,而在从 GroupMe 的朋友那里了解到了DynamoDB的优势后,同时 DynamoDB 看起来也很划算,因此我们决定迁移到DynamoDB。

在DynamoDB上犯的早期错误

与引入所有新技术的情形一样,DynamoDB在开始时看起来并不理想。最初,我们面对的最大问题就是缺少一个使用Go语言编写的成熟客户端,现在Go已经成为了我们的主要语言。然而,当我们弄清楚需要了解的API查询后,工作已经可以继续展开。也就是这个时候,我们开始犯一些真正的错误。

  • 错误1:无视吞吐量异常

这是个明摆着的坑,因为在 错误处理文档 中有着很清晰的描述。DynamoDB拥有两种类型的http错误:retryable和non-retryable。其中,最常见的retryable错误就是吞吐量异常。Dynamo的定价模式是为每个吞吐量付费,读和写可分开配置。而Amazon控制总吞吐量容量的方式是阻挡任何超过设置的查询,由客户端来处理错误,并通过一个exponential backoff来重试请求。在开始时,我们并没有重视这个问题,然而在生产环境中,任何使用率等级下你都可能受到这个限制。因此,请确保你已经对这种常见的错误类型进行处理。

  • 错误2:不理解分区如何影响吞吐量

所有的DynamoDB表格都会默认进行分区,而每个分区都会获得预分配(购买)容量的一部分。计算起来非常简单:

Total Provisioned Throughput / Partitions = Throughput Per Partition

这样带来的问题就是,如果你没有基于哈希键设计一个很好的分布式查询模式,你实际使用的吞吐量可能只是你购买的一部分。如果你对这个模式没有充分的理解,那么将会带来巨大的麻烦。

同样需要注意的是,存在的分区总数量并不是直接对你可见的(当下,已经存在一些非常不错的 向导 让你弄清楚分区的总数量)。在DynamoDB,一张表可以有1个分区也可能有1000个分区, 这就意味着很难去预测一个 hotkey。同时,当表格逐渐增长,它所分配的总分区数量也在逐渐增长。这就意味着,除非你达到一定规模,你可能根本就不会注意到hotkey问题。因此,处理这个问题最好的途径就是弄清楚分布式哈希键的设计和使用。

  • 错误3:哈希键设计较差

DynamoDB表格只能配置一个哈希键,或者哈希和范围键的组合。Timehop使用的是时间序列数据,因此需要使用范围键。然而在DynamoDB,哈希键总会映射给一个分区的单一虚拟节点,因此,哈希键上的大型范围键集很可能会导致hot-key问题。在对历史邮件进行深度挖掘时,一些写入容量图表阐明了这个问题:

互联网时光机Timehop:每天5000用户到5.5万用户 DynamoDB起到了什么作用? 互联网时光机Timehop:每天5000用户到5.5万用户 DynamoDB起到了什么作用?

红线表示的是预分配吞吐量,也就是说你可以使用的最大容量,蓝色线表示的是实际吞吐量使用。

左图显示的是我们当下的状态,通过良好的哈希键设计(基于user id和calendar date)获得。

右图显示的是2014年3月的尝试情况,那个时候哈希键设计只基于user id。看到了差距?那个时候的设计确实很烂。但是在良好设计之前,我们曾3次加载和摧毁整个表格。

进阶课程

当我们停止犯错后,我们开始持续优化DynamoDB的使用模式,并减少成本。虽然这些点已经存在于开发者指引中,但是我们必须针对实际用例进行调整。

  • 课程1:划分你的哈希键

如上文所述,每个哈希键总会映射给一个分区的单一虚拟节点。这就意味着,与哈希键关联的范围键同样会映射给这个节点。如果Timehop的一个用户拥有5000个内容项(当下的初略平均数字),而大部分内容都在同一个时间点附近写入,那么就会导致一个非常热的哈希键。在这里,你唯一可以做的就是将数据划分到多个哈希键上。当然,这样做有利有弊:

  1. 好处:通过每个哈希键分区,哈希键分布性呈线性增加,吞吐量异常显著减少。
  2. 坏处:通过划分多个哈希键,写入相同数量数据所需要的网络查询数量同样线性增加;I/O错误和网络延时的可能性都会增加。

在Timehop,我们使用的哈希键划分策略是用例的自然函数:我们根据日期划分所有用户数据。这个策略显著地提升了我们哈希键分布。举个例子,一个用户在7年内通过社交媒体行为生成了5000内容项,那么在分布上我们几乎可以获得2500倍的提升:

Without partitioning (ie: hash key = “<user_id>”):

5000 items per hash key on average

With partitioning (ie: hash key = “<date>:<user_id>”):

5000 / 365 days / 7 years = about 2 items per hash key on average
  • 课程2:临时分布写入行为

如前所述,如果表格只使用一个范围键可能会出现最低限度的一些节流。其中,产生错误的多少与哈希键分布式设计直接相关。无论如何,只要你想最大化吞吐量,你还需要考虑对单哈希键上的写入做临时的分布式处理。

在Timehop,当用户注册并连接他们社交媒体账号时,写入会异步进行。在任何时刻,某个哈希键子集上发生的写入都会产生严重的倾斜,这通常由最近加入的新用户引起。为了更好地实现分布式写入,我们在DynamoDB前建立了一个简单的写入缓冲器(一个托管的Redis集)。使用一个独立的进程负责将缓冲器中的选项随机取出,并将它们批写入到DynamoDB。需要注意的是,注册的用户越多,缓冲器中收录的数据就越多。这个架构的好处是,缓冲器中的数据越多,被取出数据的随机性就越强,因此在批写入时就可以获得一个更好的哈希键分布。从而,规模越大我们的写入性能就越高。

互联网时光机Timehop:每天5000用户到5.5万用户 DynamoDB起到了什么作用?

现在我们的使用模式已经趋于平稳,那么从中我们究竟获得了什么样的好处?在使用DynamoDB时,最大的收益恰恰出现在最重要的用户增长期,这刚好与我们DynamoDB策略的最终方向一致。

在2014年3月至5月的8周内,我们的用户增长从每天5000注册飙升至每天55000注册。可想而知,在那段时间我们一直高度关注着我们的基础设施。

那个阶段也曾出现过很多状况。图片上每次下降基本上都代表着一些故障或者后端服务被负载压垮,但是下降绝对不代表DynamoDB的宕机或性能问题。事实上,不管我们表格增加到什么规模,或者我们向表格中写入多少行(现在的数字是每天大约1亿次),延时被严格地控制在毫秒级别,通常是4到6。

在通常情况下(除了少许吞吐量异常增加的时候),DynamoDB对我们都是透明的,我们不需要去操心基础设施状态。对于Timehop Engineering来说这是一种全新的体验,而在过去,用户的高速增长通常会为我们带来数据瓶颈。DynamoDB的稳定和性能让我们可以将精力投入基础设施的其他部分,并让我们有足够的信心来应对以后的用户注册峰值。

特别强调,AWS对DynamoDB的描述是“任何规模下个位数毫秒的延时”。我们曾问过DynamoDB团队数据库的极限究竟在哪里,而得到的答案是在分配足够服务器的情况下,这里根本不存在任何限制。当下我们的表格已经非常大了,接近100TB,但是性能与第一天建立时根本没任何区别。

原文链接: https://medium.com/building-timehop/one-year-of-dynamodb-at-timehop-f761d9fe5fa

互联网时光机Timehop:每天5000用户到5.5万用户 DynamoDB起到了什么作用? 订阅“AWS中文技术社区”微信公众号,实时掌握AWS技术及产品消息!

AWS中文技术社区为广大开发者提供了一个Amazon Web Service技术交流平台 ,推送AWS最新资讯、技术视频、技术文档、精彩技术博文等相关精彩内容,更有AWS社区专家与您直接沟通交流!快加入AWS中文技术社区,更快更好的了解AWS云计算技术。

( 翻译/薛童阳  责编/王玉平 )

正文到此结束
Loading...