处理 DynamoDB batchGetItem 的 unprocessedKeys 的好习惯是什么
What's a good practice for dealing with DynamoDB batchGetItem's unprocessedKeys
我们在过去几周开始在我们的项目中使用 DynamoDB,既作为缓存又作为系统中发生的事件的列表(请不要讨论为什么有更好的替代方案来实现这个,我'我在选择 DynamoDB 之前就争论过,但没有结果。
似乎由于预配的吞吐量限制,我应该在我的代码中实现一种方法,以便在超过限制时重试未处理的项目。这是有道理的,但它也提出了有关批处理操作或查询的问题,我自己似乎无法回答这些问题。
我认为 BatchPutItem 很容易实现。如果我得到未处理的项目,我只使用指数重试,这些项目最终将被保留。我正在做这样的事情:
(...)
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。
不是我问的问题的真正答案(我真的不认为有答案,请随时纠正我),但我 re-worked 我思考问题的方式和它实际上感觉像是一个设计精良的解决方案,一点也不hacky。仔细想想就很明显了,但我完全想念了几天,所以我认为它值得分享。
我最终仅将重试逻辑放在 GetBatchItem 的客户端上,这样我就可以显示可以立即检索的结果。我的后端代码 100% 没有任何未处理项目的重试逻辑。
我的后端端点 returns 一个项目列表和一个未处理的密钥列表,如您所料。
{
"items": [{
"myPartitionKey": "whatever",
"mySortKey": "whocares",
"item": "myitem"
}, (...)],
"unprocessedKeys": [{
"pKey": "unprocessed1"
"sKey": "blah"
}, (...)]
}
然后由我的 ReactJs 客户端根据成功接收到的数据部分更新 UI 并仅使用丢失的键再次调用相同的服务,并进行某种指数退避。
我们在过去几周开始在我们的项目中使用 DynamoDB,既作为缓存又作为系统中发生的事件的列表(请不要讨论为什么有更好的替代方案来实现这个,我'我在选择 DynamoDB 之前就争论过,但没有结果。
似乎由于预配的吞吐量限制,我应该在我的代码中实现一种方法,以便在超过限制时重试未处理的项目。这是有道理的,但它也提出了有关批处理操作或查询的问题,我自己似乎无法回答这些问题。
我认为 BatchPutItem 很容易实现。如果我得到未处理的项目,我只使用指数重试,这些项目最终将被保留。我正在做这样的事情:
(...)
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。
不是我问的问题的真正答案(我真的不认为有答案,请随时纠正我),但我 re-worked 我思考问题的方式和它实际上感觉像是一个设计精良的解决方案,一点也不hacky。仔细想想就很明显了,但我完全想念了几天,所以我认为它值得分享。
我最终仅将重试逻辑放在 GetBatchItem 的客户端上,这样我就可以显示可以立即检索的结果。我的后端代码 100% 没有任何未处理项目的重试逻辑。
我的后端端点 returns 一个项目列表和一个未处理的密钥列表,如您所料。
{
"items": [{
"myPartitionKey": "whatever",
"mySortKey": "whocares",
"item": "myitem"
}, (...)],
"unprocessedKeys": [{
"pKey": "unprocessed1"
"sKey": "blah"
}, (...)]
}
然后由我的 ReactJs 客户端根据成功接收到的数据部分更新 UI 并仅使用丢失的键再次调用相同的服务,并进行某种指数退避。