2017-01-23 6 views
1

Wir begannen DynamoDB in den letzten Wochen in unserem Projekt, sowohl als Cache und als eine Liste der Ereignisse im System (bitte lassen Sie uns nicht verstehen, warum es gibt) bessere Alternativen, um dies zu implementieren, habe ich argumentiert, dass ich vor DynamoDB ohne Ergebnis gewählt wurde).Was ist eine gute Methode für den Umgang mit DynamoDB batchGetItems unprocessedKeys

Es scheint, dass aufgrund der bereitgestellten Durchsatzbegrenzung, ich in meinem Code eine Möglichkeit implementieren soll, unbearbeitete Elemente erneut zu versuchen, wenn die Grenzen überschritten werden. Es macht Sinn, wirft aber auch Fragen zu Batch-Operationen oder Abfragen auf, die ich alleine nicht zu beantworten vermag.

Ich denke, das BatchPutItem ist einfach genug zu implementieren. Wenn ich unbearbeitete Items bekomme, verwende ich einfach einen exponentiellen Retry und die Items werden schließlich beibehalten. Ich mache so etwas wie dieses:

(...) 
BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(new TableWriteItems(tableName).withItemsToPut(items)); 
processUnprocessed(outcome, 0); 
(...) 

und

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); 
} 

Da asynchrone Hintergrundaufgaben der DB bevölkern, das funktioniert gut.

Für eine Abfrage oder ein BatchGetItem ist es jedoch nicht so einfach. Der Endbenutzer wartet auf die Ausgabe des DynamoDB-Aufrufs. Ich kann hier keine exponentielle Wiederholung versuchen, sonst könnte der Benutzer sehr lange warten. Auf der anderen Seite kann ich auch nicht alle Ergebnisse für die Schlüssel anzeigen, nach denen ich frage.

Hat jemand einen Vorschlag für den richtigen Weg (ich würde mich mit einem vernünftigen Weg begnügen), damit umzugehen? Komme ich das Problem falsch an?

Ich benutze das Amazon JavaSDK BTW.

Antwort

1

Nicht wirklich die Antwort auf die Frage, die ich gestellt habe (und ich glaube wirklich nicht, dass es einen gibt, fühle mich frei, mich zu korrigieren), aber ich überarbeitete die Art, wie ich über das Problem nachdachte und es fühlt sich tatsächlich an eine gut durchdachte Lösung und überhaupt nicht Hacky. Es ist ziemlich offensichtlich, wenn man darüber nachdenkt, aber ich habe es für ein paar Tage komplett vermisst, also dachte ich, es wäre es wert, geteilt zu werden.

Ich landete die Wiederholungslogik auf dem Client nur für das GetBatchItem, so dass ich die Ergebnisse anzeigen kann, die sofort abgerufen werden konnte. Mein Backend-Code ist zu 100% frei von Wiederholungslogik für nicht verarbeitete Elemente.

Mein Backend-Endpunkt gibt erwartungsgemäß eine Liste mit Elementen und einer Liste nicht bearbeiteter Schlüssel zurück.

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

Dann ist es bis zu meinem ReactJs Client teilweise die Benutzeroberfläche zu aktualisieren basierend auf den Daten erfolgreich empfangen und den gleichen Service zu rufen wieder nur mit den fehlenden Schlüssel, mit irgendeiner Art von Exponential Backoff.

Verwandte Themen