Amazon DVA-C02: Amazon DynamoDB e Progettazione NoSQL — Guida allo studio
Fa parte della AWS Developer Associate DVA-C02 — Guida allo studio. Esercitati con risposte verificate nel centro esami Amazon, oppure fai test cronometrati su ExamRoll.io.
Modellazione dei dati e pattern di accesso
La progettazione di DynamoDB inizia con i pattern di accesso: ogni query deve corrispondere a una chiave primaria, un global secondary index (GSI) o un local secondary index (LSI); la progettazione della tabella è guidata da come l’applicazione legge e scrive gli elementi, non da come sarebbe strutturato uno schema relazionale. Scegliere una chiave di partizione ad alta cardinalità per evitare partizioni hot e utilizzare una chiave primaria composita (chiave di partizione + chiave di ordinamento) quando sono necessarie query di intervallo; le operazioni Query richiedono un’uguaglianza sulla chiave di partizione e una KeyConditionExpression opzionale sulla chiave di ordinamento. Per gli SDK, preferire le astrazioni Document di DynamoDB: utilizzare DynamoDBDocumentClient con l’AWS SDK for JavaScript v3 (il marshalling/unmarshalling è gestito automaticamente) o il DynamoDB Enhanced Client in Java per mappare oggetti ad attributi. Implementare i pattern a tabella singola (single-table) solo quando i pattern di lettura condividono le chiavi e si possono codificare i tipi di elemento tramite un attributo di tipo; utilizzare GSI sparsi (sparse GSI) per esporre percorsi di accesso secondari, scrivendo gli attributi solo negli elementi che ne hanno bisogno. Una trappola comune è l’abuso dell’operazione Scan: la scansione di tabelle di grandi dimensioni è costosa e paginata (LastEvaluatedKey); preferire Query con ProjectionExpression per ridurre l’utilizzo di RCU. Per le scritture condizionali, utilizzare UpdateItem con ConditionExpression o TransactWriteItems per l’atomicità su più elementi; gestire l’eccezione ConditionalCheckFailedException e implementare un backoff con jitter.
Indici, query e pattern transazionali
I local secondary index (LSI) vengono creati solo al momento della creazione della tabella, condividono la stessa chiave di partizione della tabella di base e consumano la capacità di lettura della tabella per le query, mentre i GSI possono essere aggiunti dopo la creazione della tabella, hanno una capacità indipendente o fatturazione on-demand e consentono chiavi di partizione diverse. Le chiamate Query utilizzano KeyConditionExpression e ExpressionAttributeNames/Values; le espressioni di proiezione (projection expression) riducono il trasferimento di dati. I GSI sono eventually consistent per impostazione predefinita e comportano un costo di scrittura aggiuntivo, poiché ogni scrittura sulla tabella di base che proietta attributi indicizzati crea scritture corrispondenti nel GSI — pianificare le WCU di conseguenza e monitorare ConsumedWriteCapacityUnits per l’indice. Per la strong consistency, utilizzare GetItem o Query con ConsistentRead=true sulla tabella di base (i GSI non supportano letture strongly consistent). Le transazioni (TransactWriteItems e TransactGetItems) garantiscono l’atomicità su un massimo di 25 elementi o 4 MB di payload; utilizzare ReturnValuesOnConditionCheckFailure per ispezionare i fallimenti. BatchWriteItem e BatchGetItem sono limitati rispettivamente a 25 e 100 elementi e non sono transazionali; il codice dovrebbe gestire gli UnprocessedItems rieseguendo il tentativo con un backoff esponenziale. Un errore frequente è dimenticare i costi e le implicazioni della eventual consistency dei GSI quando si migrano le join relazionali negli indici.
Modalità di capacità, ottimizzazione delle prestazioni e troubleshooting
Scegliere tra capacità con provisioning (provisioned) e on-demand in base alla prevedibilità: la modalità con provisioning e Auto Scaling (Application Auto Scaling per DynamoDB) offre controllo su RCU/WCU e costi per carichi di lavoro stabili, mentre la modalità on-demand semplifica la gestione del traffico con picchi (bursty) senza necessità di pianificare la capacità, ma a un prezzo per richiesta più elevato. Abilitare l’Auto Scaling con un’utilizzazione target e più policy di scalabilità; monitorare le metriche di CloudWatch come ConsumedReadCapacityUnits, ConsumedWriteCapacityUnits, ThrottledRequests, SuccessfulRequestLatency, SystemErrors e ConditionalCheckFailedRequests per rilevare hotspot e throttling. Utilizzare la capacità adattiva (adaptive capacity) per mitigare il throttling su una singola chiave, ma evitare di farvi affidamento — progettare per una distribuzione uniforme delle chiavi. Per carichi di lavoro con molte letture (read-heavy), considerare DAX per letture nell’ordine dei microsecondi o una cache con Amazon ElastiCache; per carichi write-heavy, utilizzare il write sharding (prefissi o bucket) per distribuire le scritture tra le partizioni. Eseguire il troubleshooting ispezionando l’eccezione ProvisionedThroughputExceededException e implementando un backoff esponenziale con jitter nei client SDK, abilitare CloudWatch Contributor Insights per trovare le chiavi “hot” (hot key) e utilizzare una Parallel Scan per analisi una tantum su larga scala con worker segmentati. Ricordare il limite di dimensione degli elementi (400 KB) e che elementi di grandi dimensioni aumentano il consumo di RCU/WCU; suddividere i blob di grandi dimensioni in S3, conservando i metadati in DynamoDB quando necessario.
Stream, integrazioni, backup e best practice operative
I DynamoDB Streams acquisiscono le modifiche a livello di elemento (INSERT, MODIFY, REMOVE) in ordine per chiave di partizione e si integrano direttamente con Lambda tramite una mappatura della fonte di eventi (event source mapping) (configurare startingPosition come TRIM_HORIZON o LATEST, impostare batchSize e maximumBatchingWindowInSeconds, e ottimizzare bisectBatchOnError e maximumRetryAttempts). Per un’elaborazione robusta, utilizzare Lambda con una Dead-Letter Queue (SQS o SNS) o instradare i record dello stream in Kinesis o Kinesis Data Firehose per l’analisi. Abilitare il Time To Live (TTL) per la scadenza automatica degli elementi; notare che le eliminazioni TTL vengono elaborate in modo eventually consistent e non dovrebbero essere usate per ottenere una coerenza immediata. Utilizzare il Point-in-Time Recovery (PITR) e i backup on-demand per il disaster recovery; per la disponibilità multi-regionale, usare le Global Tables per replicare le modifiche tra le regioni. Applicare ruoli IAM con il principio del privilegio minimo (least-privilege) ai servizi e concedere solo le azioni necessarie dynamodb:Query, dynamodb:PutItem, dynamodb:UpdateItem, dynamodb:GetItem, dynamodb:DescribeStream e dynamodb:ListStreams per le funzioni Lambda. Le trappole operative comuni includono la mancanza di logica di retry/backoff nei consumer, una pianificazione inadeguata della capacità dei GSI e la mancata monitorizzazione dell’IteratorAge degli Stream per il rilevamento del lag; strumentare con CloudWatch Logs e X-Ray per tracciare la latenza end-to-end.
Problema Pratico: Scenario d’Uso
Scenario: AcmeMedia gestisce un catalogo di metadati in una singola tabella DynamoDB in us-east-1 che contiene decine di milioni di elementi. Una pipeline di elaborazione immagini appena lanciata necessita di una query a bassa latenza per photographerId e un intervallo di uploadTimestamp, e i consumer Lambda a valle devono elaborare le modifiche in modo affidabile.
Sfida: Aggiungere un percorso di query efficiente per photographerId + intervallo di timestamp senza riprogettare la tabella, garantire che i processi Lambda a valle elaborino i record dello stream con semantica at-least-once ed evitare partizioni hot per i fotografi più prolifici.
Approccio Raccomandato:
- Creare un GSI chiamato
photographer-gsicon chiave di partizionephotographerIde chiave di ordinamentouploadTimestamp; usare l’APIUpdateTableo la console per aggiungere il GSI e specificare la fatturazioneProvisionedThroughputoOn-DemandtramiteUpdateTablee impostare il monitoraggio diIndexStatus. - Durante la scrittura degli elementi, includere gli attributi
photographerIdeuploadTimestampin modo che la proiezione dell’indice sia sparsa; scegliereProjectionType=INCLUDEcon gli attributi non-chiave necessari per le query per ridurre i costi di archiviazione e scrittura. - Configurare i DynamoDB Streams come
ENABLEDsulla tabella e creare una mappatura della fonte di eventi Lambda constartingPosition=TRIM_HORIZON,batchSizeottimizzato (es. 100),bisectBatchOnError=true,maximumRetryAttempts=2, e impostare una coda SQS come destinazione Dead-Letter (Dead-Letter Destination) nella configurazione della funzione Lambda. - Implementare i tentativi di retry del client SDK con jitter (usare la strategia di retry integrata nell’AWS SDK) e applicare il write sharding se un singolo
photographerIdcausa ancora throttling (aggiungere un prefisso aphotographerIdcon N bucket in scrittura e rimuovere il prefisso lato client in lettura).
Motivazione: L’aggiunta di un GSI espone il pattern di accesso richiesto senza modificare la chiave primaria di base; proiettare solo gli attributi necessari riduce il costo di scrittura del GSI. Streams + Lambda con DLQ e controlli di retry forniscono un’elaborazione affidabile at-least-once, mentre lo sharding protegge dalle partizioni hot derivanti da traffico ad alta cardinalità.
← Amazon API Gateway e Integrazione di applicazioni · Tutti i domini · CloudFormation e Infrastruttura come Codice (SAM →
Esercitati su queste domande → · Pratica cronometrata su ExamRoll.io →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
Supera l'esame →