我一直在测试我们打算在今年夏天在我们的prod帐户中进行的大型数据迁移到发电机。我运行了一个测试,将大约32亿个文档批量写入我们的dynamo表,该表具有散列和范围键以及两个部分索引。每个文件都很小,不到1k。虽然我们在大约3天内成功获得了这些项目,但我们对我们所经历的Dynamo表现感到失望,并且正在寻找关于我们如何改进事物的建议。
为了进行此迁移,我们使用了2个ec2实例(c4.8xlarges)。每个程序最多可运行10个迁移程序;我们通过一些内部参数在流程之间拆分工作,并且知道某些流程的运行时间比其他流程要长。每个进程查询我们的RDS数据库以查找100,000条记录。然后我们将它们分成25个分区,并使用10个线程的线程池来调用DynamoDB java SDK的batchSave()方法。每次调用batchSave()时,只发送25个文档,每个文档少于1k,因此我们希望每个文档只向AWS发出一次HTTP调用。这意味着在任何给定时间,我们可以在服务器上拥有多达100个线程,每个线程调用具有25条记录的batchSave。我们的RDS实例在此期间处理了对它的查询负载,我们的2个EC2实例也是如此。在ec2方面,我们没有最大化我们的CPU,内存或网络或网络输出。我们的写入不是按散列键分组的,因为我们知道可以减慢发电机写入速度。通常,在一组100,000个记录中,它们分为88,000个不同的哈希键。我最初创建了Dynamo表,其写入吞吐量为30,000,但在测试期间的一个点上配置了高达40,000的写入吞吐量,因此我们的理解是发电机侧至少有40个分区来处理这个问题。
我们在整个这段时间里看到了对batchSave()发电机调用的非常多变的响应时间。对于每个ec2实例运行100个线程的20分钟的一个跨度,平均时间为0.636秒,但中位数仅为0.374,因此我们有很多通话需要超过一秒钟。我希望看到从EC2实例到发电机进行这些调用所需的时间更加一致。我们的发电机表似乎配置了大量的吞吐量,并且EC2实例的CPU低于10%,并且网络输入和输出看起来都很健康,但不会接近最大化。控制台中的CloudWatch图表(相当糟糕......)并没有显示任何写入请求的限制。
在我完成这些采样时间后,我们的一些进程完成了他们的工作,因此我们在ec2实例上运行的线程更少。当发生这种情况时,我们在发电机调用中看到了显着改善的响应时间。例如当我们在ec2实例上运行40个线程而不是100个线程时,每个线程调用batchSave,响应时间提高了5倍以上。但是,即使响应时间越来越长,我们也没有看到提高的写入吞吐量。似乎无论我们将写入吞吐量配置为什么,我们从未真正看到实际吞吐量超过15,000。
我们希望了解如何最好地在这样的Dynamo迁移上实现更好的性能。今年夏天我们的生产迁移将是时间敏感的,当然,到那时,我们将寻求迁移大约40亿条记录。有没有人对如何实现整体更高的吞吐率有任何建议?如果我们愿意在迁移过程中为主索引支付30,000单位的写入吞吐量,那么我们如何才能真正实现接近这一目标的性能呢?
答案 0 :(得分:2)
BatchWrite延迟的一个组成部分是批处理中占用时间最长的Put请求。考虑到你必须循环遍历DynamoDBMapper.FailedBatch列表,直到它为空,你可能没有足够快地取得进展。考虑运行多个并行DynamoDBMapper.save()调用而不是batchSave,以便您可以为您编写的每个项目独立进行。
同样,Cloudwatch指标是1分钟指标,因此您可能会有1分钟窗口屏蔽的消耗和限制峰值。默认情况下,SDK会在将ProvisionedThroughputExceededException暴露给客户端之前重试受限制的调用10 times,这使得很难确定实际限制发生的时间和地点。为了提高您的理解,请尝试减少SDK重试次数,请求ConsumedCapacity = TOTAL,使用Guava RateLimiter自我限制您的写入,如rate-limited scan blog post中所述,并记录受限制的主键以查看是否出现任何模式。< / p>
最后,表的分区数不仅由您在表上提供的读写容量单位数量驱动。它还受您在表中存储的数据量的驱动。通常,分区最多可存储10GB数据,然后进行拆分。因此,如果您只是在不删除旧条目的情况下写入表,则表中的分区数将不受限制地增长。这导致IOPS饥饿 - 即使您配置40000 WCU / s,如果由于数据量已经有80个分区,则40k WCU将分布在80个分区中,平均每个分区500 WCU。要控制表中陈旧数据的数量,您可以使用速率限制清理过程来扫描和删除旧条目,或使用rolling time-series tables(幻灯片84-95)并删除/迁移整个数据表,因为它们变得不太相关。滚动时间序列表比速率限制清理便宜,因为您不使用带有DeleteTable操作的WCU,而每个DeleteItem调用至少消耗1个WCU。