DynamoDB Conteggi dei riferimenti
Un conteggio riferimenti è un numero memorizzato su un articolo principale che ne tiene traccia gli elementi secondari lo puntano: Mi piace su un post, membri in uno spazio di lavoro, risposte su a commento. Lo tieni perché contare i bambini a ogni lettura è troppo costoso.
Come mantieni il conteggio in DynamoDB?
Memorizza il totale parziale come numero sull'elemento padre e aggiornalo nella stessa scrittura che crea l'elemento figlio. UNfa atterrare entrambi o nessuno dei due, e una condizione sulla scrittura figlio impedisce i tentativi di doppio conteggio, quindi un singolo GetItem restituisce un conteggio accurato.
- Non contare i bambini durante la lettura. Un
Queryper contare i Mi piace paga per ogni come l'oggetto che scansiona. Memorizza il totale sul post e leggi invece un elemento. - Mantieni il conteggio dove è scritto il bambino, non dopo. Sbattetelo lo stesso operazione che crea il bambino in modo che i due non vadano mai alla deriva.
- Utilizzare aquando la scrittura e l'urto toccano elementi diversi. Un simile è un oggetto, il conteggio vive su un altro: "TransactWriteItems" fa atterrare entrambi o nessuno dei due.
- Il footgun è un doppio conteggio. Un tentativo ripetuto o duplicato del genere esegue nuovamente il l'incremento gonfia il numero. Proteggi il bambino che scrive con una condizione.
Perché contare?
Venendo da SQL, non memorizzeresti mai il conteggio dei Mi piace: dovresti SELECT COUNT(*) FROM Mi piace WHERE post_id = ? e lascia che un indice lo renda economico. DynamoDB non ha COUNT(*)
salta la lettura degli elementi.
Un Query sui Mi piace di un post legge (e fattura) ogni elemento simile in quel post
partizione, anche se desideri solo il numero. In un post virale che è migliaia
RCUs per rispondere "quanti Mi piace?" Questo è il numero di riferimenti letti per le armi da fuoco che esistono per uccidere.
Quindi tu: memorizza il totale parziale sul post stesso. Lettura del conteggio
diventa un singolo GetItem. Il costo è che ora possiedi mantenendolo accurato.
Modella gli oggetti
Due tipi di elementi condividono una partizione in modo che il post e i suoi Mi piace si trovino in uno raccolta di elementi. Chiavi inventate:
| PK | SK | attributes |
|---|---|---|
| POST#a91f | META | likeTally (Number), body, authorId, createdAt |
| PK | SK | attributes |
|---|---|---|
| POST#a91f | LIKE#USER#7c20 | likedAt |
L'attributo "likeTally" sull'elemento "META" è il conteggio dei riferimenti. Ogni MI PIACE#
l'oggetto è un bambino. Mettendoli entrambi sotto PK = "POST#a91f" significa che un singolo Query può
recupera il post e i suoi Mi piace insieme quando vuoi l'elenco.
Aumenta il conteggio in modo atomico
DynamoDB incrementa un numero con un ADD (o SET x = x + :n)—
questo è un contatore atomico: DynamoDB applica il delta lato server senza di te
leggendo prima il valore corrente, in modo che gli incrementi simultanei non si ostacolino a vicenda.
(AWS: contatori atomici)
Mettere mi piace a un post significa due scrivere su due elementi: creare MI PIACE#
elemento e aggiungi "1" a "likeTally" su "META". Se il simile atterra ma l'urto fallisce, il
il conteggio è sbagliato per sempre. Hai bisogno di entrambi o di nessuno dei due.
Questo è ciò che garantisce TransactWriteItems: tutto o niente su più elementi,
e annulla l'intera transazione se qualsiasi elemento viene modificato contemporaneamente
(AWS: blocco pessimistico con transazioni):
{
"TransactItems": [
{
"Put": {
"TableName": "Social",
"Item": {
"PK": {"S": "POST#a91f"},
"SK": {"S": "LIKE#USER#7c20"},
"likedAt": {"N": "1750636800"}
},
"ConditionExpression": "attribute_not_exists(SK)"
}
},
{
"Update": {
"TableName": "Social",
"Key": {
"PK": {"S": "POST#a91f"},
"SK": {"S": "META"}
},
"UpdateExpression": "ADD likeTally :one",
"ExpressionAttributeValues": {":one": {"N": "1"}}
}
}
]
}Il Put e il Update si impegnano insieme. Se uno dei due fallisce, DynamoDB lancia entrambi
back e restituisce una TransactionCanceledException.
Proteggiti dai doppi conteggi
Il vero bug non è scritto a metà: la transazione lo impedisce. È il allo stesso utente piace due volte oppure un client riprova a riprodurre la richiesta. Ogni replay aggiunge un altro "1" e "likeTally" supera tranquillamente il conteggio reale.
Il ConditionExpression: attributo_not_exists(SK) sul Put è la guardia. Se
l'elemento LIKE# di quell'utente esiste già, la condizione di Put fallisce, il tutto
la transazione viene annullata e, aspetto critico, "ADD" non viene mai eseguito. Un Mi piace per utente,
imposto dalla chiave.
Costruisci e copia queste espressioni di aggiornamento e condizione, con il diritto
ExpressionAttributeValues e attribute_not_exists proteggono — nel file
DynamoDB Expression Builder anziché
assemblando a mano il JSON.
A differenza, e il costo
Rimuovere un Mi piace è l'immagine speculare: Elimina l'elemento LIKE# con
ConditionExpression: attributo_esiste(SK) e ADD likeTally :minusOne nel
stessa transazione. La condizione impedisce a una doppia differenza di determinare un conteggio negativo.
Conosci il prezzo. Una scrittura transazionale costa 2 WCUs per articolo per articoli fino a 1 KB — uno per prepararsi, uno per impegnarsi - contro 1 WCU per una semplice scrittura. Un mi piace è composto da due elementi, quindi ogni mi piace vale circa quattro WCU. Economico per azione, ma vale la pena saperlo prima di a il post di una celebrità prende una tempesta.
Vedilo in DynoTable
Quando sospetti che un conteggio sia andato alla deriva, vuoi confrontare il likeTally memorizzato
rispetto al numero effettivo di bambini "LIKE#" - senza eseguire una query di conteggio in prod.

Per una vera riconciliazione attraverso una serie limitata di post - "che i conteggi non corrispondono
il loro figlio conta?" — SQL Workbench di DynoTable esegue GROUP BY e il join
lato client sulle righe che hai caricato, che semplicemente PartiQL non può esprimere.
Insidie e passaggi successivi
- Non mantenere il conteggio fuori banda (una Lambda che conta di notte). È un cerotto su un percorso di scrittura che avrebbe dovuto essere transazionale fin dall'inizio.
- Orologio. Un unico post estremamente popolare concentra tutti i Mi piace — e ogni riscontro di conteggio su una chiave di partizione. Il conteggio è corretto; la partizione potrebbe ancora rallentare.
- Riconciliare raramente, riparare chirurgicamente. La deriva dovrebbe essere prossima allo zero per ogni mutazione è condizionato. Tratta una mancata corrispondenza come un bug da trovare, non come un numero da sovrascrivere.
Lettura correlata: design a tabella singola per il motivo del post e Mi piace condividono una partizione e Query vs Scan per il motivo contare i bambini al momento della lettura è lo schema che stai evitando.
Quindi scarica DynoTable per ispezionare queste raccolte di articoli e verificare il tuo corrisponde ai tuoi stessi tabelle.


