2017-01-23 8 views
1

Мы начали использовать DynamoDB за последние несколько недель в нашем проекте, как в качестве кеша, так и в виде списка событий, которые произошли в системе (не будем вдаваться в то, почему лучшие альтернативы для реализации этого, я утверждал, что сам, прежде чем DynamoDB был выбран без результата).Что такое хорошая практика для работы с unprocessedKeys от DynamoDB batchGetItem

Похоже, что из-за предусмотренного ограничения пропускной способности я должен реализовать в своем коде способ повторного запуска необработанных элементов при превышении лимитов. Это имеет смысл, но также вызывает вопросы о пакетных операциях или запросах, которые я, похоже, не могу ответить самостоятельно.

Я думаю, что 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 кстати.

ответ

1

Не совсем ответ на вопрос, который я задал (и я действительно не думаю, что есть один, не стесняйтесь, поправляйте меня), но я переработал способ, которым я думал о проблеме, и на самом деле это похоже на хорошо разработанное решение, а не хаки. Это довольно очевидно, когда вы об этом думаете, но я полностью потерял его на пару дней, поэтому я подумал, что это стоит того.

В итоге я поставил логику повторения на клиенте только для GetBatchItem, чтобы показать результаты, которые можно было сразу получить. Мой внутренний код на 100% свободен от любой логики повтора для необработанных элементов.

My backend endpoint возвращает список элементов и список unprocessedKeys, как и следовало ожидать.

{ 
    "items": [{ 
    "myPartitionKey": "whatever", 
    "mySortKey": "whocares", 
    "item": "myitem" 
    }, (...)], 
    "unprocessedKeys": [{ 
    "pKey": "unprocessed1" 
    "sKey": "blah" 
    }, (...)] 
} 

Тогда это до моего ReactJs клиента, чтобы частично обновить пользовательский интерфейс, основанный на данных, успешно получил и позвонить в ту же услугу снова только с отсутствующими ключами, с какой-то показательной потери мощности.