【问题标题】:DynamoDB - very slow write operationsDynamoDB - 非常慢的写入操作
【发布时间】:2015-06-23 12:51:03
【问题描述】:

我有一个在 AWS 云中运行的 DynamoDB,我正在使用常规(计划)基础上的数据填充它。基本上,每小时一次,我会收到一个需要处理的文件,并且必须将结果保存在数据库中。

我正在使用以下类来处理数据库连接并执行批量写入:

public class DynamoDBService {

  private final AmazonDynamoDB amazonDynamoDB = new AmazonDynamoDBClient();
  private final DynamoDBMapper mapper = new DynamoDBMapper(amazonDynamoDB);

  @Value("${aws_region}")
  private String region;

  @PostConstruct
  public void init() {
    log.info("Region: {}", region);
    amazonDynamoDB.setRegion(RegionUtils.getRegion(region));
  }

  /**
   * 
   * @param records
   */
  public void saveRecord(final Collection<Record> records) {
    log.info("Saving records...");

    // create table if necessary here

    List<Record> recordsToSave = new ArrayList<Record>(100);

    for (Record record : records) {

      recordsToSave.add(record);

    }

    // save the records
    List<FailedBatch> failedBatch = mapper.batchWrite(recordsToSave, new ArrayList<Record>());
    // process failed writes here

    log.info("All records have been saved.");
  }
}

问题是写入速度非常缓慢。我阅读了文档并增加了吞吐能力(因此它现在应该支持超过 300000 次写入/小时),但处理一个包含大约8000 条记录。

我读到一个批处理操作中的最佳写入次数是 25 次,并且一条记录的大小低于 1kb。我在本地机器(我知道由于流量开销会比较慢)和 AWS 工作环境中都对其进行了测试,但结果都很慢。有什么方法可以优化这个过程吗?

【问题讨论】:

  • 您配置的写入吞吐量是多少?执行此操作时消耗了什么?您是否在这些电话中受到限制(可能是single partition throughput exceeded)?您是否在单个线程上编写所有这些记录(可能是 IO 绑定的)?您是否尝试过增加连接池的大小?
  • 我强烈建议您通过分析器运行您的代码(即:JProfiler)以缩小问题范围。根据给定的信息,它可以是任何东西——使用遥远的区域(增加延迟)、写入限制、热哈希键、转换记录的问题,或者完全其他的东西。来自分析器的信息会让您知道调查的重点。另外,您的记录/表格是什么样的?如果您有很多具有相同哈希键(或定义不明确的 LSI/GSI)的记录,这可能是罪魁祸首。

标签: java amazon-web-services amazon-dynamodb


【解决方案1】:

首先,为了使您在多个线程中没有多个 DynamoDBMapper/客户端实例,请将 Mapper 和 AmazonDynamoDB 客户端都设为静态。其次,您应该使用 Guava RateLimiter 或类似工具进行自我节流。将速率设置为等于您在表上配置的每秒写入次数,并在每次调用 batchWrite 之前获取 25 个许可,只要您的项目小于 1KB。第三,您可以并行运行 mapper.batchWrite 调用。每小时 300000 次写入大约是每秒 83 次写入。这意味着您的表可能有 1 个分区,只要存储在表中的数据量小于 10GB(我假设这是真的)。第四,可以减少客户端配置中的dynamodb.timeout。这可能会有所帮助,因为 BatchWrite 操作与批处理中最潜在的单个 PutRequest 一样潜在。您也可以尝试减少或关闭 SDK 重试次数。

请注意,分区上每秒支持的最大写入次数为 1000。您过去可能已向上配置太多,导致表因 IOPS 而分裂。如果您有一个 Hash+Range 模式并且您将许多项目写入相同的哈希键但不同的范围键,那么所有这些写入都将进入同一个分区。因此,即使您的表上所有写入容量的总和可能是每秒 83 次写入,您也可能会遇到这样一种情况:您有很多分区并且分区级别的写入配置不足以支持您的负载。

在这种情况下,有两种方法是可能的。您可以开始对散列键进行分区,并使用 key1、key2、key3 等作为相同逻辑“键”的散列键,并在项目的范围键上使用散列和模除法来决定项目应该使用哪个散列键分区被写入。第二个也是更可取的选择是评估您的架构,以确保您的写入在哈希范围键空间中均匀分布。

【讨论】:

    猜你喜欢
    • 2012-05-27
    • 1970-01-01
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 2021-05-09
    • 2018-05-07
    • 2016-05-23
    相关资源
    最近更新 更多