Scritture

Questa pagina elenca i tipi di richieste di scrittura che puoi inviare a Bigtable e descrive quando utilizzarli e quando non utilizzarli. Per informazioni sull'aggregazione dei dati in una cella al momento della scrittura, consulta Aggrega i valori al momento della scrittura.

L'API Bigtable Data e le librerie client ti consentono di scrivere dati nelle tabelle in modo programmatico. Bigtable invia una risposta o una conferma per ogni scrittura.

Ogni libreria client offre la possibilità di inviare i seguenti tipi di richieste di scrittura:

  • Scritture semplici
  • Incrementi e aggiunte
  • Scritture condizionali
  • Scritture batch

Le librerie client di Bigtable dispongono di una funzionalità integrata di tentativi di ripetizione intelligenti per le scritture semplici e batch, il che significa che gestiscono senza problemi la non disponibilità temporanea. Ad esempio, se la tua applicazione tenta di scrivere dati e riscontra un'interruzione temporanea o un problema di rete, riprova automaticamente finché la scrittura non viene eseguita o non viene raggiunta la scadenza della richiesta. Questa resilienza funziona sia con istanze a cluster singolo che con istanze replicate, con routing a cluster singolo o routing multi-cluster.

Per le operazioni di scrittura in batch e in flussi, puoi utilizzare il connettore Bigtable Beam. Per saperne di più, consulta Scritture in batch.

Per scoprire i limiti che si applicano alle richieste di scrittura, consulta Quote e limiti.

Per esempi di librerie client di Cloud Bigtable delle richieste di scrittura descritte in questa pagina, consulta Esempi di scrittura.

Tipi di scrittura e quando utilizzarli

Tutte le richieste di scrittura includono i seguenti componenti di base:

  • Il nome della tabella in cui scrivere.
  • Un ID profilo dell'app, che indica a Bigtable come instradare il traffico.
  • Una o più mutazioni. Una mutazione è costituita dai seguenti elementi:
    • Nome famiglia di colonne
    • Qualificatore di colonna
    • Timestamp
    • Valore che stai scrivendo nella tabella

Il timestamp di una mutazione ha un valore predefinito che corrisponde alla data e all'ora correnti, misurate come il tempo trascorso dall'epoca di Unix, 00:00:00 UTC del 1° gennaio 1970.

Per impostazione predefinita, un timestamp che invii a Bigtable deve essere un valore in microsecondi con una precisione massima di un millisecondo. Bigtable rifiuta i timestamp con precisione in microsecondi, ad esempio 3023483279876543, a meno che tu non scriva in una tabella con granularità timestamp in microsecondi. Le tabelle con granularità di microsecondi accettano timestamp forniti dall'utente con precisione completa dei microsecondi. Questa funzionalità è disponibile solo per le istanze della versione Enterprise Plus.

Tutte le mutazioni in una singola richiesta di scrittura hanno lo stesso timestamp, a meno che non venga eseguito l'override. Puoi impostare il timestamp di tutte le mutazioni in una richiesta di scrittura in modo che sia uguale o diverso l'uno dall'altro.

Scritture semplici

Puoi scrivere una singola riga in Bigtable con una richiesta MutateRow che include il nome della tabella, l'ID del profilo dell'app da utilizzare, una chiave di riga e fino a 100.000 mutazioni per quella riga. Una scrittura su una singola riga è atomica. Utilizza questo tipo di scrittura quando apporti più mutazioni a una singola riga.

Per esempi di codice che mostrano come inviare richieste di scrittura semplici, consulta Esecuzione di una scrittura semplice.

Quando non utilizzare le scritture semplici

Le scritture semplici non sono il modo migliore per scrivere dati per i seguenti casi d'uso:

  • Stai scrivendo un batch di dati che avrà chiavi di riga contigue. In questo caso, devi utilizzare le scritture in batch anziché le scritture semplici consecutive, perché un batch contiguo può essere applicato in una singola chiamata di backend.

  • Vuoi un throughput elevato (righe al secondo o byte al secondo) e non hai bisogno di una bassa latenza. In questo caso, le scritture in batch saranno più veloci.

Aggiornamenti incrementali

Bigtable ti consente di creare celle con un tipo di dati aggregato. Le celle aggregate sono ottimizzate per i casi in cui vuoi modificare i valori nelle celle di una tabella esistente, aggregando i valori delle celle man mano che i dati vengono scritti. Sono disponibili i seguenti tipi di aggregazione:

  • Somma: incrementa un contatore o mantieni una somma parziale.
  • Minimo: invia un numero intero a una cella e Bigtable mantiene il valore più basso tra i due.
  • Massimo: invia un numero intero a una cella e Bigtable conserva il valore più alto tra i due.
  • HyperLogLog (HLL): invia un valore che viene aggiunto a un insieme probabilistico di tutti i valori aggiunti alla cella.

Le richieste di aggiornamento delle celle aggregate vengono inviate con una richiesta MutateRow e un tipo di mutazione AddToCell o MergeToCell o uno dei tipi di mutazione di eliminazione.

Aggiungi

Per aggiungere dati a un valore esistente, puoi utilizzare una richiesta ReadModifyWriteRow. Questa richiesta include il nome della tabella, l'ID del profilo dell'app da utilizzare, una chiave di riga e un insieme di regole da utilizzare per la scrittura dei dati. Ogni regola include il nome della famiglia di colonne, il qualificatore di colonna e un valore di aggiunta o un importo di incremento.

Le regole vengono applicate in ordine. Ad esempio, se la richiesta include una richiesta di aggiungere il valore per una colonna che contiene il valore some con la stringa thing e una regola successiva nella stessa richiesta aggiunge la stessa colonna con body, il valore viene modificato due volte in una singola scrittura atomica e il valore risultante è somethingbody. La regola successiva non sovrascrive quella precedente.

Puoi anche incrementare un numero intero con una chiamata ReadModifyWriteRow, ma ti consigliamo di utilizzare celle aggregate e AddToCell o MergeToCell. Un valore può essere incrementato utilizzando ReadModifyWrite solo se è codificato come un numero intero con segno big-endian a 64 bit. Bigtable tratta un incremento di un valore vuoto o inesistente come se il valore fosse zero.

Le richieste ReadModifyWriteRow sono atomiche. Non vengono ripetuti se non vanno a buon fine per qualsiasi motivo.

Quando non utilizzarli ReadModifyWriteRow

Non inviare richieste ReadModifyWriteRow nelle seguenti situazioni:

  • Il tuo caso d'uso può essere gestito inviando una richiesta MutateRow con una mutazione AddToCell. Per saperne di più, consulta Aggregazione dei valori in fase di scrittura.

  • Stai utilizzando un profilo dell'app con routing multi-cluster.

  • Utilizzi più profili di app a cluster singolo e invii scritture che potrebbero entrare in conflitto con i dati scritti nella stessa riga e colonna in altri cluster nell'istanza. Con il routing a un cluster singolo, una richiesta di scrittura viene inviata a un singolo cluster e poi replicata.

  • Ti affidi alla funzionalità di tentativi di ripetizione intelligenti fornita dalle librerie client. Non è possibile riprovare una richiesta ReadModifyWriteRow.

  • Stai scrivendo grandi quantità di dati e hai bisogno che le scritture vengano completate rapidamente. Una richiesta che legge e poi modifica una riga è più lenta di una semplice richiesta di scrittura. Di conseguenza, questo tipo di scrittura spesso non è l'approccio migliore su larga scala.

    Ad esempio, se vuoi contare qualcosa che si aggira nell'ordine dei milioni, come le visualizzazioni di pagina, devi MutateRow con una mutazione AddToCell per aggiornare i conteggi al momento della scrittura.

Scritture condizionali

Se vuoi verificare una condizione per una riga e poi, a seconda del risultato, scrivere dati in quella riga, invia una richiesta CheckAndMutateRow. Questo tipo di richiesta include una chiave di riga e un filtro di riga. Un filtro di riga è un insieme di regole che utilizzi per controllare il valore dei dati esistenti. Le mutazioni vengono quindi applicate a colonne specifiche della riga solo quando vengono soddisfatte determinate condizioni, verificate dal filtro. Questo processo di controllo e scrittura viene completato come un'unica azione atomica.

Una richiesta di filtro deve includere uno o entrambi i seguenti tipi di mutazioni:

  • Mutazioni true o mutazioni da applicare se il filtro restituisce un valore.
  • False mutations, che vengono applicate se il filtro non restituisce alcun risultato.

Puoi fornire fino a 100.000 mutazioni di ogni tipo (true e false) in una singola scrittura e devi inviarne almeno una. Bigtable invia una risposta quando tutte le mutazioni sono state completate.

Poiché una scrittura condizionale legge la riga per valutare il filtro, il chiamante deve disporre delle autorizzazioni bigtable.tables.readRows e bigtable.tables.mutateRows sulla tabella (o delle autorizzazioni equivalenti bigtable.authorizedViews.readRows e bigtable.authorizedViews.mutateRows su una vista autorizzata). Per saperne di più, consulta Controllo dell'accesso.

Per esempi di codice che mostrano come inviare scritture condizionali, consulta Scrittura condizionale di un valore.

Quando non utilizzare le scritture condizionali

Non puoi utilizzare le scritture condizionali per il seguente caso d'uso:

  • Stai utilizzando un profilo dell'app con routing multi-cluster.

  • Utilizzi più profili di app a cluster singolo e invii scritture che potrebbero entrare in conflitto con i dati scritti nella stessa riga e colonna in altri cluster dell'istanza. Con il routing a un cluster singolo, una richiesta di scrittura viene inviata a un singolo cluster e poi replicata.

  • Stai scrivendo grandi quantità di dati e hai bisogno che le scritture vengano completate rapidamente. Analogamente a ReadModifyWriteRow, le richieste di scrittura condizionale devono leggere le righe prima di modificarle, pertanto le richieste CheckAndModifyRow sono più lente delle richieste di scrittura semplici. Di conseguenza, questo tipo di scrittura spesso non è l'approccio migliore su larga scala.

Scritture batch

Puoi scrivere più di una riga con una singola chiamata utilizzando una richiesta MutateRows. Le richieste MutateRows contengono un insieme di massimo 100.000 voci,ognuna delle quali viene applicata in modo atomico. Ogni voce è costituita da una chiave di riga e da almeno una mutazione da applicare alla riga. Una richiesta di scrittura in batch può contenere fino a 100.000 mutazioni distribuite su tutte le voci. Ad esempio, una scrittura in batch potrebbe includere una delle seguenti permutazioni:

  • 100.000 voci con 1 mutazione in ogni voce.
  • 1 voce con 100.000 mutazioni.
  • 1000 voci con 100 mutazioni ciascuna.

Ogni voce di una richiesta MutateRows è atomica, ma la richiesta nel suo complesso non lo è. Se necessario, Bigtable riprova a inserire le voci del batch che non sono andate a buon fine, finché tutte le scritture non vanno a buon fine o non viene raggiunta la scadenza della richiesta. Quindi restituisce una risposta che identifica ogni scrittura nel batch e se la scrittura è andata a buon fine o meno.

Per esempi di codice che mostrano come inviare scritture in batch, consulta Esecuzione di scritture in batch.

Quando non utilizzare le scritture in batch

  • Stai scrivendo dati collettivi in righe non vicine tra loro. Bigtable archivia i dati in modo lessicografico in base alla chiave di riga, l'equivalente binario dell'ordine alfabetico. Per questo motivo, quando le chiavi di riga di una richiesta non sono simili tra loro, Bigtable le gestisce in sequenza anziché in parallelo. Il throughput sarà elevato, ma anche la latenza sarà elevata. Per evitare questa latenza elevata, utilizza MutateRows quando le chiavi di riga sono simili e Bigtable scrive righe vicine tra loro. Utilizza MutateRow o scritture semplici per le righe che non sono vicine tra loro.

  • Stai richiedendo più mutazioni alla stessa riga. In questo caso, otterrai prestazioni migliori se esegui tutte le mutazioni in un'unica richiesta di scrittura semplice. Questo perché in una scrittura semplice viene eseguito il commit di tutte le modifiche in un'unica azione atomica, mentre una scrittura in batch è costretta a serializzare le mutazioni nella stessa riga, causando latenza.

Controllo del flusso di scrittura in batch

Se invii le scritture in batch (incluse le eliminazioni) utilizzando uno dei seguenti metodi, puoi attivare il controllo di flusso delle scritture in batch nel codice.

Quando il controllo di flusso della scrittura in batch è abilitato per un job Dataflow, Bigtable esegue automaticamente quanto segue :

  • Limita la frequenza del traffico per evitare di sovraccaricare il cluster Bigtable
  • Assicura che il cluster sia sottoposto a un carico sufficiente per attivare la scalabilità automatica di Bigtable (se abilitata), in modo che vengano aggiunti automaticamente altri nodi al cluster quando necessario

Queste azioni combinate impediscono il sovraccarico del cluster e l'errore del job, senza che sia necessario scalare manualmente il cluster in previsione dell'esecuzione della scrittura in batch. Quando il controllo di flusso è abilitato, la scalabilità del cluster avviene durante il job Dataflow anziché prima, quindi il job potrebbe richiedere più tempo per essere completato rispetto alla scalabilità manuale del cluster.

Devi utilizzare un profilo dell'app configurato per il routing a cluster singolo. L'attivazione della scalabilità automatica di Bigtable per il cluster di destinazione non è un requisito, ma la scalabilità automatica ti consente di sfruttare appieno il controllo del flusso di scrittura in batch. Puoi utilizzare la scalabilità automatica di Dataflow come faresti con qualsiasi altro job.

Per saperne di più sulla scalabilità automatica di Bigtable, consulta Scalabilità automatica. Per comprendere le policy di routing dei profili app, consulta la panoramica dei profili app.

Per esempi di codice, consulta Attiva il controllo di flusso delle scritture in batch.

Scrivi dati in una vista autorizzata

Per scrivere dati in una visualizzazione autorizzata, devi utilizzare uno dei seguenti elementi:

  • gcloud CLI
  • Client Bigtable per Java

Le altre librerie client di Bigtable non supportano ancora l'accesso alle visualizzazioni autorizzate.

Quando scrivi dati in una vista autorizzata, devi fornire l'ID della vista autorizzata oltre all'ID della tabella.

Tutte le scritture in una vista autorizzata vengono applicate direttamente alla tabella sottostante.

Limitazioni della definizione della vista autorizzata

In una vista autorizzata, le righe o le colonne in cui puoi scrivere dati sono limitate dalla definizione della vista autorizzata. In altre parole, puoi scrivere solo su righe e colonne che soddisfano gli stessi criteri specificati per la vista autorizzata.

Ad esempio, se la vista autorizzata è definita dal prefisso della chiave di riga examplepetstore1, non puoi scrivere dati utilizzando una chiave di riga examplepetstore2; l'inizio del valore della chiave di riga deve includere l'intera stringa examplepetstore1.

Analogamente, se la vista autorizzata è definita dal prefisso del qualificatore di colonna order-phone, puoi scrivere i dati utilizzando il qualificatore di colonna order-phone123, ma non puoi utilizzare il qualificatore di colonna order-tablet.

La richiesta di scrittura non può fare riferimento a dati esterni alla vista autorizzata, ad esempio quando controlli un valore in una richiesta di scrittura condizionale.

Per qualsiasi richiesta che scrive o fa riferimento a dati al di fuori della vista autorizzata, viene restituito un messaggio di errore PERMISSION_DENIED.

Replica

Quando un cluster di un'istanza replicata riceve una scrittura, questa viene immediatamente replicata negli altri cluster dell'istanza.

Atomicità

Ogni richiesta MutateRows che invii a un'istanza replicata viene eseguita come singola azione atomica sul cluster a cui viene indirizzata la richiesta. Quando la scrittura viene replicata negli altri cluster dell'istanza, anche questi cluster ricevono la scrittura come operazione atomica. I cluster non ricevono mutazioni parziali; una mutazione ha esito positivo o negativo in modo atomico per tutte le celle che modifica.

Coerenza

Il tempo necessario affinché i dati scritti siano disponibili per la lettura dipende da diversi fattori, tra cui il numero di cluster nell'istanza e il tipo di routing utilizzato dal profilo dell'app.

Con un'istanza a cluster singolo, i dati possono essere letti immediatamente, ma se un'istanza ha più di un cluster, ovvero utilizza la replica, Bigtable ha una coerenza finale. Puoi ottenere la coerenza read-your-writes indirizzando le richieste allo stesso cluster.

Puoi creare e utilizzare un token di coerenza e chiamare CheckConsistency in modalità StandardReadRemoteWrites dopo aver inviato le richieste di scrittura. Il token verifica la coerenza della replica. In genere, crei un token di coerenza dopo l'invio di un batch di scritture o dopo un determinato intervallo, ad esempio un'ora. Puoi quindi passare il token per utilizzarlo in un altro processo, ad esempio un modulo che effettua una richiesta di lettura, che utilizza il token per verificare che tutti i dati siano stati replicati prima di tentare la lettura.

Se utilizzi un token subito dopo averlo creato, potrebbero essere necessari alcuni minuti per verificarne la coerenza la prima volta che lo utilizzi. Questo ritardo è dovuto al fatto che ogni cluster controlla tutti gli altri per assicurarsi che non arrivino altri dati. Dopo l'utilizzo iniziale o se attendi diversi minuti per utilizzare il token per la prima volta, il token viene eseguito correttamente ogni volta che viene utilizzato.

Risoluzione dei conflitti

Ogni valore di cella in una tabella Bigtable è identificato in modo univoco dalla tupla di quattro elementi (chiave di riga, famiglia di colonne, qualificatore di colonna, timestamp). Per maggiori dettagli su questi identificatori, consulta Modello di archiviazione di Bigtable. Nel caso in cui due scritture con la stessa quadrupla vengano inviate a due cluster diversi, Bigtable risolve automaticamente il conflitto utilizzando un algoritmo interno "last write wins" basato sull'ora lato server. L'implementazione "last write wins" di Bigtable è deterministica e, quando la replica viene completata, tutti i cluster hanno lo stesso valore per la quadrupla.

Passaggi successivi