2017-01-23 120 views
1

我們在過去的幾周內在我們的項目中開始使用DynamoDB,既作爲緩存,也作爲系統中發生的事件列表(請讓我們不要理解爲什麼有更好的替代方案來實現這一點,我認爲在DynamoDB被選中之前我自己沒有結果)。處理DynamoDB的最佳做法batchGetItem的未處理鍵

看來由於預配置的吞吐量限制,我期望在我的代碼中實現一種方法,在超出限制時重試未處理的項目。它是有道理的,但它也提出了有關批量操作或查詢的問題,這些問題我自己似乎無法回答。

我認爲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調用的輸出。我不能在這裏做指數重試,否則用戶可能會等待很長時間。另一方面,我也不能不顯示我要求的鑰匙的所有結果。

有沒有人有任何建議,正確的方式(我會解決一個體面的方式)處理這個? 我是否以錯誤的方式接近問題?

我正在使用亞馬遜JavaSDK順便說一句。

回答

1

對於我所問的問題(我真的不認爲有一個,請隨時糾正我)並不是真正的答案,但我重新以我考慮問題的方式工作,而且它實際上感覺像一個設計良好的解決方案,而不是hacky。當你考慮這個問題時很明顯,但是我幾天完全忽略了它,所以我認爲這是值得分享的。

我最終將重試邏輯放在GetBatchItem的客戶端上,這樣我就可以顯示可以直接檢索的結果。我的後端代碼100%不含任何未處理項目的重試邏輯。

我的後端端點按照您的預期返回項目列表和未處理的鍵列表。

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

然後它給我的ReactJs客戶端更新部分基於數據成功接收的UI,並只與丟失的鑰匙再次調用同樣的服務,與某種指數退避的。