过去几周,我们在项目中开始使用 DynamoDB,既作为缓存,也作为系统中发生的事件列表(请不要讨论为什么有更好的替代方案来实现这一点,我自己之前曾争论过选择了 DynamoDB,但没有结果)。
似乎由于预置的吞吐量限制,我希望在我的代码中实现一种在超出限制时重试未处理项目的方法。这是有道理的,但它也提出了关于批处理操作或查询的问题,我似乎无法自己回答。
我认为 BatchPutItem 很容易实现。如果我得到 unprocesseditems,我只需使用指数重试,这些项目最终将被持久化。我正在做这样的事情:
(...)
BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(new TableWriteItems(tableName).withItemsToPut(items));
processUnprocessed(outcome, 0);
(...)
和
private void processUnprocessed(BatchWriteItemOutcome outcome, int retryNumber) {
if (MapUtils.isEmpty(outcome.getUnprocessedItems())) {
return;
}
if (retryNumber > maxRetries) {
log.error(Joiner.on(" ").join("Unable to process", outcome.getUnprocessedItems().size(), "items after", retryNumber, "tries"));
return;
}
long retryTime = (long)Math.pow(retryFactor, retryNumber);
log.info("Exceeded provisioning throughput. Retrying in " + retryTime);
try {
Thread.sleep(retryTime);
} catch (InterruptedException e) {
log.error(e.getMessage());
}
processUnprocessed(dynamoDB.batchWriteItemUnprocessed(outcome.getUnprocessedItems()), ++retryNumber);
}
因为异步后台任务正在填充数据库,所以这工作正常。
然而,对于查询或 BatchGetItem,它并不是那么简单。最终用户正在等待 DynamoDB 调用的输出。我不能在这里进行指数重试,否则用户可能会等待很长时间。另一方面,我也不能不显示我要求的键的所有结果。
有没有人对处理这个问题的正确方式(我会选择一种体面的方式)有任何建议?我是否以错误的方式处理问题?
我正在使用 Amazon JavaSDK 顺便说一句。