emr-dynamodb-connector写入DDB触发吞吐量超限如何限流
问题根因
dynamodb.throughput.write.percent参数默认仅对预配置吞吐量(Provisioned Capacity)模式的DynamoDB表生效。你使用的是按需容量(On-demand)模式,emr-dynamodb-connector默认不会自动探测该模式下表的吞吐阈值做限速,仅靠percent参数无法控制实际写入速率,最终流量突刺触发账户级吞吐量限制。
可生效的限速配置方案
按以下步骤调整配置即可稳定控制写入速率,避免限流报错:
- 显式指定总写入WCU上限:新增
dynamodb.throughput.write参数,手动设置作业允许使用的最大写入容量单位值,该参数不受表的容量模式影响,设置后会强制触发connector的限速逻辑。比如你的账户级总写入软限制为20000 WCU,可以将该值设为15000,预留足够冗余,配合你原有的0.5的write percent参数,实际最大写入速率会被控制在7500 WCU,不会打满账户阈值。 - 限制单任务写入速率:新增
dynamodb.throughput.write.maxmaprate参数,设置每个map task每秒允许写入的最大WCU(建议设为50-200),避免单任务产生瞬时流量尖刺。 - 开启指数退避重试:新增重试相关配置,遇到临时限流时connector会自动等待降速,不会直接抛出异常终止作业。
- 控制写入并发度:写入前对RDD做重分区,将分区数调整到和总写入速率匹配的值,避免默认过高的分区数导致大量并发请求同时打向DynamoDB。
修正后的完整配置代码如下:
JobConf ddbConfWrite = new JobConf(spark.sparkContext().hadoopConfiguration()); ddbConfWrite.set("dynamodb.output.tableName", tableName); // 显式指定总写入WCU上限,按需模式下必须配置该参数才能触发生效限速 ddbConfWrite.set("dynamodb.throughput.write", "15000"); // 实际最大写入速率 = dynamodb.throughput.write * dynamodb.throughput.write.percent ddbConfWrite.set("dynamodb.throughput.write.percent", "0.5"); // 单map task最大写入速率,避免流量突刺 ddbConfWrite.set("dynamodb.throughput.write.maxmaprate", "100"); // 配置指数退避重试参数 ddbConfWrite.set("dynamodb.retry.sleep.base", "100"); ddbConfWrite.set("dynamodb.retry.sleep.max", "2000"); ddbConfWrite.set("mapred.input.format.class", "org.apache.hadoop.dynamodb.read.DynamoDBInputFormat"); ddbConfWrite.set("mapred.output.format.class", "org.apache.hadoop.dynamodb.write.DynamoDBOutputFormat"); // 调整写入分区数:按总7500WCU、单task承载100WCU计算,设置为75个分区控制并发 ddbInsertFormattedRDD.coalesce(75).saveAsHadoopDataset(ddbConfWrite);
额外注意事项
- 按需容量模式的DDB表存在流量爬坡机制:新表或长期处于低流量的表,初始写入峰值仅支持每分钟1000 WCU,之后每30分钟可承载的峰值会翻倍,最高可达单表40000 WCU。如果你的总写入量远高于初始阈值,建议初始阶段把总写入WCU设到1000以下,运行30分钟后再逐步调高参数,避免触发表级限流。
- 如果同账号下有其他DDB表同时承载写入流量,设置总WCU上限时要扣除其他表占用的容量,建议预留20%-30%的冗余,不要卡着账户总限制设值。
- 如果长期需要运行TB级别的批量导入作业,可以提前申请提升账号级DynamoDB写入软限制,减少作业运行时长。
内容的提问来源于stack exchange,提问作者Sunny Gupta
相关产品推荐
相关产品推荐

