Modelli di consistenza DAX e DynamoDB - Amazon DynamoDB

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Modelli di consistenza DAX e DynamoDB

Amazon DynamoDB Accelerator (DAX) è un servizio di memorizzazione nella cache write-through progettato per semplificare il processo di aggiunta di una cache alle tabelle DynamoDB. Poiché DAX opera separatamente da DynamoDB, è importante comprendere i modelli di consistenza sia di DAX che di DynamoDB in modo da assicurarsi che le applicazioni si comportino come previsto.

In molti casi d'uso, il modo in cui l'applicazione utilizza DAX influenza la coerenza dei dati all'interno del cluster DAX e quella dei dati tra DAX e DynamoDB.

Consistenza tra i nodi del cluster DAX

Per ottenere un'alta disponibilità dell'applicazione, è preferibile effettuare il provisioning del cluster DAX con almeno tre nodi e di posizionare tali nodi in più zone di disponibilità all'interno di una regione.

Durante l'esecuzione, il cluster DAX replica i dati tra tutti i nodi del cluster (supponendo che sia stato effettuato il provisioning di più di un nodo). Si consideri un'applicazione che esegue un'operazione UpdateItem riuscita tramite DAX. Tale operazione determina la modifica della cache degli elementi del nodo primario con il nuovo valore, il quale viene quindi replicato in tutti gli altri nodi nel cluster. Questa replica è di tipo consistente finale e richiede in genere meno di un secondo per il completamento.

In questo scenario, è possibile che due client leggano la stessa chiave dallo stesso cluster DAX ma ricevano valori diversi, a seconda del nodo a cui ciascun client accede. I nodi sono tutti consistenti dopo che l'aggiornamento è stato completamente replicato in tutti i nodi del cluster. Questo comportamento è simile alla natura di consistenza finale di DynamoDB.

Se si sta creando un'applicazione che utilizza DAX, questa deve essere progettata in modo da poter tollerare dati a consistenza finale.

Comportamento della cache di elementi DAX

Ogni cluster DAX dispone di due cache distinte: una cache di elementi e una cache di query. Per ulteriori informazioni, consultare DAX: come funziona.

In questa sezione vengono descritte le implicazioni della coerenza relative alla lettura e alla scrittura nella cache di elementi DAX.

Consistenza delle letture

Con DynamoDB, l'operazione GetItem esegue una lettura a consistenza finale per impostazione predefinita. Si supponga di utilizzare UpdateItem con il client DynamoDB. Se tenti di leggere lo stesso item subito dopo, è possibile che i dati visualizzati siano quelli relativi a prima dell'aggiornamento. Ciò è dovuto al ritardo di propagazione all'interno di tutte le posizioni di archiviazione di DynamoDB. La consistenza si ottiene generalmente in pochi secondi. è probabile che l'item aggiornato venga visualizzato dopo un nuovo tentativo di lettura.

Quando si utilizza GetItem con il client DAX, l'operazione (in questo caso, una lettura a consistenza finale) procede come mostrato di seguito.

Diagramma di flusso di lavoro che mostra la procedura con fasi numerate per l'aggiornamento di un item.
  1. Il client DAX emette una richiesta GetItem. DAX cerca di leggere l'elemento richiesto dalla cache di elementi. Se l'elemento si trova nella cache (hit della cache), DAX lo restituisce all'applicazione.

  2. Se l'elemento non è disponibile (mancato riscontro nella cache), DAX esegue un'operazione GetItem a consistenza finale in DynamoDB.

  3. DynamoDB restituisce l'elemento richiesto e DAX lo archivia nella cache di elementi.

  4. DAX restituisce l'elemento all'applicazione.

  5. (Non visualizzato) Se il cluster DAX contiene più di un nodo, l'elemento viene replicato in tutti gli altri nodi del cluster.

Il nuovo elemento rimane nella cache di elementi DAX, soggetto all'impostazione durata (TTL, Time to Live) e all'algoritmo utilizzato meno di recente (LRU) della cache. Per ulteriori informazioni, consultare DAX: come funziona.

Tuttavia, durante questo periodo, DAX non legge nuovamente l'elemento da DynamoDB. Se un altro utente aggiorna l'elemento tramite un client DynamoDB, ignorando del tutto DAX, una richiesta GetItem che utilizza il client DAX genererà risultati diversi rispetto alla stessa richiesta GetItem che utilizza il client DynamoDB. In questo scenario, DAX e DynamoDB contengono valori incoerenti per la stessa chiave finché il TTL dell'elemento DAX non scade.

Se un'applicazione modifica i dati all'interno di una tabella DynamoDB sottostante, ignorando DAX, è necessario anticipare e tollerare le incoerenze che potrebbero verificarsi nei dati.

Nota

Oltre a GetItem, il client DAX supporta anche le richieste BatchGetItem. BatchGetItem è essenzialmente un wrapper intorno a una o più richieste GetItem, pertanto DAX tratta ognuna di queste come una singola operazione GetItem.

Consistenza delle scritture

DAX è una cache write-through che semplifica il processo di mantenimento della coerenza della cache di elementi DAX con le tabelle DynamoDB sottostanti.

Il client DAX supporta le stesse operazioni API di scrittura di DynamoDB (PutItem, UpdateItem DeleteItem, BatchWriteItem e TransactWriteItems). Quando si utilizzano tali operazioni con il client DAX, gli elementi vengono modificati sia in DAX che in DynamoDB. DAX aggiorna gli elementi nella cache degli elementi, a prescindere dal valore TTL degli elementi.

Ad esempio, si assuma di aver emesso una richiesta GetItem dal client DAX per leggere un elemento dalla tabella ProductCatalog. La chiave di partizione è Id; non è presente una chiave di ordinamento. Recupera l'item il cui Id è 101. Il valore QuantityOnHand per quell'elemento è 42. DAX archivia l'elemento nella sua cache di elementi con un TTL specifico. Supponiamo che il TTL di questo esempio sia 10 minuti. Dopo tre minuti, un'altra applicazione utilizza il client DAX per aggiornare lo stesso elemento in modo che il suo valore QuantityOnHand ora sia 41. Ipotizzando che l'item non venga nuovamente aggiornato, tutte le letture successive dello stesso item nei 10 minuti successivi restituiscono il valore memorizzato nella cache di QuantityOnHand (41).

Come DAX elabora le scritture

DAX è destinato all'uso in applicazioni che richiedono letture ad alte prestazioni. Come cache write-through, DAX passa le scritture a DynamoDB in modo sincrono, quindi replica automaticamente e in maniera asincrona gli aggiornamenti risultanti nella cache degli elementi in tutti i nodi del cluster. Non è necessario gestire la logica dell'invalidamento della cache perché verrà gestita automaticamente da DAX.

DAX supporta le operazioni di scrittura seguenti: PutItem, UpdateItem, DeleteItem, BatchWriteItem e TransactWriteItems.

Quando si invia una richiesta PutItem, UpdateItem, DeleteItem o BatchWriteItem a DAX, si verifica quanto segue:

  • DAX invia la richiesta a DynamoDB.

  • DynamoDB risponde a DAX, confermando l'esito positivo della scrittura.

  • DAX scrive l'elemento nella sua cache di elementi.

  • DAX riporta al richiedente che l'operazione è stata eseguita correttamente.

Quando si invia una richiesta TransactWriteItems a DAX, si verifica quanto segue:

  • DAX invia la richiesta a DynamoDB.

  • DynamoDB risponde a DAX, confermando che la transazione è stata completata.

  • DAX riporta al richiedente che l'operazione è stata eseguita correttamente.

  • In background, DAX effettua una richiesta TransactGetItems per ogni elemento nella richiesta TransactWriteItems per archiviare l'elemento nella cache di elementi. TransactGetItems viene usato per garantire un isolamento serializzabile.

Se una scrittura su DynamoDB non va a buon fine per un qualsiasi motivo, inclusa la limitazione, l'elemento non viene memorizzato nella cache in DAX. e il richiedente riceve un'eccezione relativa all'errore. In questo modo, i dati non vengono scritti nella cache DAX a meno che non siano stati scritti prima correttamente in DynamoDB.

Nota

Ogni scrittura in DAX altera lo stato della cache di elementi. Tuttavia, le scritture nella cache degli elementi non influiscono sulla cache delle query. La cache di elementi e la cache di query DAX hanno scopi diversi e funzionano in maniera indipendente l'una dall'altra.

Comportamento della cache di query DAX

DAX memorizza nella cache i risultati delle richieste Query e Scan nella propria cache di query. Tuttavia, questi risultati non influiscono sulla cache degli elementi. Quando l'applicazione emette una richiesta Query o Scan con DAX, il set di risultati viene salvato nella cache di query, non nella cache di elementi. Non puoi preparare la cache degli elementi eseguendo un'operazione Scan perché la cache degli elementi e la cache delle query sono entità separate.

Consistenza di query-aggiornamento-query

Gli aggiornamenti della cache di elementi o della tabella DynamoDB sottostante non invalidano né modificano i risultati memorizzati nella cache di query.

A titolo illustrativo, considera il seguente scenario in cui un'applicazione utilizza la tabella DocumentRevisions, la cui chiave di partizione è DocId e la cui chiave di ordinamento è RevisionNumber.

  1. Un client emette un Query per DocId 101, per tutti gli elementi con RevisionNumber maggiore o uguale a 5. DAX archivia il set di risultati nella cache di query e lo restituisce all'utente.

  2. Il client emette una richiesta PutItem per DocId 101 con un valore RevisionNumber di 20.

  3. Il client emette la stessa richiesta Query descritta nella fase 1 (DocId 101 e RevisionNumber >= 5).

In questo scenario, il set di risultati memorizzato nella cache per la richiesta Query emessa nella fase 3 è identico al set di risultati che è stato memorizzato nella cache nella fase 1. Il motivo è che DAX non invalida i set di risultati Query o Scan in base agli aggiornamenti dei singoli elementi. L'operazione PutItem della fase 2 viene riportata nella cache di query DAX solo quando il TTL per la Query scade.

L'applicazione deve considerare il valore TTL della cache delle query e per quanto tempo l'applicazione può tollerare risultati incoerenti tra la cache delle query e la cache degli elementi.

Letture fortemente consistenti e transazionali

Per eseguire una richiesta GetItem, BatchGetItem, Query o Scan fortemente consistente, impostare il parametro ConsistentRead su true. DAX passa le richieste di lettura fortemente consistente a DynamoDB. Quando riceve una risposta da DynamoDB, DAX restituisce i risultati al client senza memorizzarli nella cache. DAX non è in grado di servire direttamente le letture fortemente consistenti in quanto non è strettamente accoppiato con DynamoDB. Per questo motivo, le eventuali letture successive di DAX devono essere letture a consistenza finale. Inoltre, le eventuali letture fortemente consistenti successive devono essere trasferite a DynamoDB.

DAX gestisce le richieste TransactGetItems nello stesso modo in cui gestisce le letture fortemente consistenti. DAX passa tutte le richieste TransactGetItems a DynamoDB. Quando riceve una risposta da DynamoDB, DAX restituisce i risultati al client ma senza memorizzarli nella cache.

Caching negativo

DAX supporta voci negative sia nella cache di elementi sia nella cache di query. Una voce negativa nella cache si verifica quando DAX non è in grado di individuare gli elementi richiesti in una tabella DynamoDB sottostante. Anziché generare un errore, DAX memorizza nella cache un risultato vuoto e lo restituisce all'utente.

Ad esempio, si assuma che un'applicazione invii una richiesta GetItem a un cluster DAX e che nella cache di elementi DAX non esista un elemento corrispondente. Ciò fa sì che DAX legga l'elemento corrispondente dalla tabella DynamoDB sottostante. Se l'elemento non esiste in DynamoDB, DAX archivia un elemento vuoto nella sua cache di elementi e lo restituisce all'applicazione. Ora supponiamo che l'applicazione invii un'altra richiesta GetItem per lo stesso articolo. DAX individua l'elemento vuoto nella cache di elementi e lo restituisce immediatamente all'applicazione. Non consulta DynamoDB.

Una voce negativa nella cache rimane nella cache di elementi DAX fino a che il TTL dell'elemento scade, viene richiamato l'algoritmo LRU o l'elemento viene modificato tramite PutItem, UpdateItem o DeleteItem.

La cache di query DAX gestisce i risultati di cache negativi in modo simile. Se un'applicazione esegue un'operazione Query o Scan e la cache di query DAX non contiene un risultato memorizzato nella cache, DAX invia la richiesta a DynamoDB. Se non sono presenti elementi corrispondenti nel set di risultati, DAX archivia un set di risultati vuoto nella cache di query e lo restituisce all'applicazione. Le richieste Query o Scan successive generano lo stesso set di risultati (vuoto) finché il TTL per tali risultati non scade.

Strategie di scrittura

Il comportamento write-through di DAX è appropriato per molti modelli di applicazione. Tuttavia, il modello write-through potrebbe non essere appropriato per tutti i modelli di applicazione.

Nel caso di applicazioni sensibili alla latenza, la scrittura tramite DAX genera un hop di rete aggiuntivo. Di conseguenza, la scrittura in DAX è leggermente più lenta rispetto alla scrittura diretta in DynamoDB. Se l'applicazione è sensibile alla latenza di scrittura, è possibile ridurre la latenza scrivendo direttamente in DynamoDB. Per ulteriori informazioni, consulta Write-Around.

Nel caso di applicazioni a scrittura intensiva (come quelle che eseguono il caricamento in blocco dei dati), è consigliabile non scrivere tutti i dati tramite DAX perché solo una piccola percentuale di tali dati viene letta dall'applicazione. Quando scrivi grandi quantità di dati tramite DAX, è necessario richiamare il relativo algoritmo LRU per fare spazio ai nuovi elementi da leggere nella cache. Ciò riduce l'efficacia di DAX come cache di lettura.

Quando si scrive un elemento in DAX, lo stato della cache di elementi viene modificato per ricevere il nuovo elemento. Ad esempio, per far spazio al nuovo elemento, DAX potrebbe dover eliminare i dati meno recenti dalla cache di elementi. Il nuovo item rimane nella cache degli elementi, soggetto all'algoritmo LRU della cache e all'impostazione TTL della cache. Finché l'elemento persiste nella cache di elementi, DAX non esegue una nuova lettura dell'elemento da DynamoDB.

Write-Through

La cache di elementi DAX implementa una policy write-through. Per ulteriori informazioni, consultare Come DAX elabora le scritture.

Quando si scrive un elemento, DAX si assicura che l'elemento memorizzato nella cache sia sincronizzato con l'elemento presente in DynamoDB. Questo è utile per le applicazioni che devono leggere nuovamente un item subito dopo averlo scritto. Tuttavia, se altre applicazioni scrivono direttamente in una tabella DynamoDB, l'elemento nella cache di elementi DAX non sarà più sincronizzato con DynamoDB.

A titolo illustrativo, considera due utenti (Alice e Bob) che utilizzano la tabella ProductCatalog. Alice accede alla tabella tramite DAX, Bob invece ignora DAX e accede alla tabella direttamente in DynamoDB.

Diagramma di flusso di lavoro che mostra la procedura con fasi numerate relativa all'accesso da parte di Alice e Bob a una tabella tramite DAX e DynamoDB.
  1. Alice aggiorna un elemento nella tabella ProductCatalog. DAX inoltra la richiesta a DynamoDB e l'aggiornamento va a buon fine. DAX scrive quindi l'elemento nella sua cache di elementi e restituisce una risposta di operazione completata ad Alice. Da quel punto in poi, fino a quando l'elemento viene definitivamente rimosso dalla cache, tutti gli utenti che leggono l'elemento da DAX vedono l'elemento con l'aggiornamento di Alice.

  2. Poco tempo dopo, Bob aggiorna lo stesso item ProductCatalog scritto da Alice. Tuttavia, Bob aggiorna l'elemento direttamente in DynamoDB. DAX non aggiorna automaticamente la sua cache di elementi in risposta agli aggiornamenti tramite DynamoDB. Di conseguenza, gli utenti di DAX non vedranno l'aggiornamento di Bob.

  3. Alice legge nuovamente l'elemento da DAX. Poiché l'elemento si trova nella cache di elementi, DAX lo restituisce ad Alice senza accedere alla tabella DynamoDB.

In questo scenario, Alice e Bob vedono rappresentazioni diverse dello stesso item ProductCatalog. Questa situazione persiste fino a quando DAX non rimuove l'elemento dalla cache di elementi o finché un altro utente aggiorna nuovamente lo stesso elemento tramite DAX.

Write-Around

Se l'applicazione deve scrivere grandi quantità di dati (come ad esempio, nel caso di un caricamento in blocco dei dati), potrebbe essere preferibile ignorare DAX e scrivere i dati direttamente in DynamoDB. Una strategia write-around (scrittura diretta) riduce la latenza di scrittura. Tuttavia, la cache di elementi non rimane sincronizzata con i dati in DynamoDB.

Se si decide di utilizzare una strategia write-around, tenere presente che DAX popola la sua cache di elementi ogni volta che le applicazioni utilizzano il client DAX per leggere i dati. In alcuni casi, ciò potrebbe rappresentare un vantaggio in quanto assicura che vengano memorizzati nella cache solo i dati letti più frequentemente (anziché i dati scritti più frequentemente).

Ad esempio, si consideri un utente (Charlie) che desidera utilizzare una tabella diversa, la tabella GameScores, tramite DAX. La chiave di partizione per GameScores è UserId, quindi tutti i punteggi di Charlie hanno lo stesso UserId.

Diagramma di flusso di lavoro che illustra la procedura con fasi numerate relativa all'utilizzo da parte di Charlie di una tabella DynamoDB tramite DAX.
  1. Charlie intende recuperare tutti i suoi punteggi, pertanto invia una Query a DAX. Ipotizzando che questa query non sia stata emessa in precedenza, DAX la inoltra a DynamoDB per l'elaborazione, Memorizza i risultati nella cache di query DAX e infine restituisce i risultati a Charlie. Il set di risultati rimane disponibile nella cache delle query finché non viene rimosso.

  2. Supponiamo ora che Charlie giochi a Meteor Blasters e ottenga un punteggio elevato. Charlie invia una richiesta UpdateItem a DynamoDB, modificando un elemento nella tabella GameScores.

  3. Infine, Charlie decide di eseguire nuovamente la richiesta Query precedente per recuperare tutti i suoi dati da GameScores. Charlie non visualizza nei risultati il suo punteggio massimo di Meteor Blasters in quanto i risultati della query provengono dalla cache delle query, non dalla cache degli elementi. Poiché le due cache sono indipendenti l'una dall'altra, le modifiche apportate in una cache non influiscono sull'altra cache.

DAX non aggiorna i set di risultati nella cache di query con i dati più recenti di DynamoDB. Ogni set di risultati nella cache delle query è attuale al momento dell'esecuzione dell'operazione Query o Scan. Pertanto, i risultati della Query di Charlie non riflettono l'operazione PutItem. Questa situazione persiste fino a quando DAX rimuove il set di risultati dalla cache di query.