Introduzione all'API BigQuery Storage Write
L'API BigQuery Storage Write è un'API unificata di importazione dati per BigQuery. che combina l'importazione di flussi di dati e il caricamento in batch in un'unica API ad alte prestazioni. Puoi utilizzare l'API Storage Write per caricare i record in BigQuery in tempo reale o per elaborare in batch un numero arbitrariamente elevato di record e sottoporli a commit in un'unica operazione atomica.
Vantaggi dell'utilizzo dell'API Storage Write
Semantica di consegna "exactly-once". L'API Storage Write supporta la semantica "exactly-once" tramite l'utilizzo degli offset dello stream. A differenza del metodo tabledata.insertAll
, l'API Storage Write non scrive mai due messaggi con lo stesso offset all'interno di uno stream, se il client fornisce gli offset dello stream quando aggiunge i record.
Transazioni a livello di stream. Puoi scrivere dati in uno stream e applicare il commit come singola transazione. Se l'operazione di commit non va a buon fine, puoi ritentare in tutta sicurezza.
Transazioni tra stream. Più worker possono creare i propri stream per elaborare i dati in modo indipendente. Quando tutti i worker hanno terminato, puoi committare tutti gli stream come transazione.
Protocollo efficiente. L'API Storage Write è più efficiente rispetto al metodo insertAll
precedente perché utilizza lo streaming gRPC anziché REST su HTTP. L'API Storage Write supporta anche i formati binari sotto forma di buffer di protocollo, che sono un formato di trasmissione più efficiente del JSON.
Le richieste di scrittura sono asincrone con ordinamento garantito.
Rilevamento degli aggiornamenti dello schema. Se lo schema della tabella sottostante cambia durante lo streaming del client, l'API Storage Write invia una notifica al client. Il client può decidere se riconnettersi utilizzando lo schema aggiornato o continuare a scrivere nella connessione esistente.
Costo inferiore. L'API Storage Write ha un costo notevolmente inferiore rispetto all'API di inserimento di flussi insertAll
precedente. Inoltre, puoi importare fino a 2 TiB al mese gratuitamente.
Autorizzazioni obbligatorie
Per utilizzare l'API Storage Write, devi disporre delle autorizzazionibigquery.tables.updateData
.
I seguenti ruoli IAM (Identity and Access Management) predefiniti includono le autorizzazioni bigquery.tables.updateData
:
bigquery.dataEditor
bigquery.dataOwner
bigquery.admin
Per ulteriori informazioni sui ruoli e sulle autorizzazioni IAM in BigQuery, consulta Ruoli e autorizzazioni predefiniti.
Ambiti di autenticazione
L'utilizzo dell'API Storage Write richiede uno dei seguenti ambiti OAuth:
https://www.googleapis.com/auth/bigquery
https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/bigquery.insertdata
Per ulteriori informazioni, consulta la Panoramica dell'autenticazione.
Panoramica dell'API Storage Write
L'astrazione di base nell'API Storage Write è uno stream. Uno stream scrive i dati in una tabella BigQuery. Più stream possono scrivere contemporaneamente nella stessa tabella.
Stream predefinito
L'API Storage Write fornisce uno stream predefinito, progettato per scenari di streaming in cui i dati arrivano continuamente. Ha le seguenti caratteristiche:
- I dati scritti nello stream predefinito sono immediatamente disponibili per le query.
- Lo stream predefinito supporta la semantica almeno una volta.
- Non è necessario creare esplicitamente lo stream predefinito.
Se esegui la migrazione dall'API tabledata.insertall
precedente, ti consigliamo di utilizzare lo stream predefinito. Ha una semantica di scrittura simile, con una maggiore resilienza dei dati e meno limitazioni di scalabilità.
Flusso dell'API:
AppendRows
(loop)
Per ulteriori informazioni e codice di esempio, consulta Utilizzare lo stream predefinito per la semantica almeno una volta.
Stream creati dall'applicazione
Puoi creare uno stream esplicitamente se hai bisogno di uno dei seguenti comportamenti:
- Semantika di scrittura esattamente una volta tramite l'utilizzo di offset dello stream.
- Supporto di proprietà ACID aggiuntive.
In generale, gli stream creati dall'applicazione offrono un maggiore controllo sulla funzionalità, ma con un costo aggiuntivo in termini di complessità.
Quando crei uno stream, devi specificare un tipo. Il tipo controlla quando i datiscritti nello stream diventano visibili in BigQuery per la lettura.
Tipo in attesa
Nel tipo in attesa, i record vengono memorizzati nella memoria intermedia in uno stato in attesa finché non esegui il commit dello stream. Quando esegui il commit di uno stream, tutti i dati in attesa diventano disponibili per la lettura. Il commit è un'operazione atomica. Utilizza questo tipo per i carichi di lavoro batch, come alternativa ai job di caricamento BigQuery. Per ulteriori informazioni, consulta Caricare i dati in batch utilizzando l'API Storage Write.
Flusso dell'API:
Tipo di impegno
Nel tipo di commit, i record sono disponibili per la lettura non appena li scrivi nello stream. Utilizza questo tipo per i carichi di lavoro in streaming che richiedono una latenza di lettura minima. Lo stream predefinito utilizza una forma almeno una volta del tipo di commit. Per ulteriori informazioni, consulta Utilizzare il tipo di commit per la semantica esattamente una volta.
Flusso dell'API:
CreateWriteStream
AppendRows
(loop)FinalizeWriteStream
(facoltativo)
Tipo di buffering
Il tipo con buffer è un tipo avanzato che in genere non deve essere utilizzato, tranne con il connettore Apache Beam BigQuery I/O. Se hai piccoli batch che vuoi garantire che vengano visualizzati insieme, utilizza il tipo impegnato e invia ogni batch in una richiesta. In questo tipo, vengono forniti commit a livello di riga e i record vengono memorizzati in un buffer fino al commit delle righe tramite svuotamento dello stream.
Flusso dell'API:
CreateWriteStream
AppendRows
⇒FlushRows
(loop)FinalizeWriteStream
(facoltativo)
Selezione di un tipo
Utilizza il seguente diagramma di flusso per decidere quale tipo è più adatto al tuo carico di lavoro:
Dettagli API
Tieni presente quanto segue quando utilizzi l'API Storage Write:
AppendRows
Il metodo AppendRows
aggiunge uno o più record allo stream. La prima chiamata a AppendRows
deve contenere un nome stream insieme allo schema dei dati, specificato come DescriptorProto
. Come
best practice, invia un batch di righe in ogni chiamata AppendRows
. Non inviare una
riga alla volta.
Gestione del buffer di proto
I buffer di protocollo forniscono un meccanismo estensibile, indipendente dal linguaggio e dalla piattaforma per la serializzazione dei dati strutturati in modo compatibile con le versioni precedenti e future. Sono vantaggiosi in quanto forniscono uno spazio di archiviazione dei dati compatto con analisi rapida ed efficiente. Per scoprire di più sui buffer di protocollo, consulta la Panoramica dei buffer di protocollo.
Se intendi utilizzare l'API direttamente con un messaggio predefinito del buffer di protocollo, il messaggio del buffer di protocollo non può utilizzare un specificatore package
e tutti i tipi nidificati o di enumerazione devono essere definiti all'interno del messaggio principale di primo livello.
Non sono consentiti riferimenti a messaggi esterni. Per un esempio, consulta
sample_data.proto.
I client Java e Go supportano buffer di protocollo arbitrari, perché la libreria client normalizza lo schema del buffer di protocollo.
FinalizeWriteStream
Il metodo FinalizeWriteStream
finalizza lo stream in modo che non sia possibile aggiungere nuovi dati. Questo metodo è obbligatorio nel tipo
Pending
e facoltativo nei tipi
Committed
e
Buffered
. Lo stream predefinito non supporta questo metodo.
Gestione degli errori
Se si verifica un errore, l'oggetto google.rpc.Status
restituito può includere un valore StorageError
nei dettagli dell'errore. Esamina
StorageErrorCode
per trovare il tipo di errore specifico. Per maggiori informazioni sul modello di errore dell'API Google, consulta Errori.
Connessioni
L'API Storage Write è un'API gRPC che utilizza connessioni bidirezionali. Il metodo AppendRows
crea una connessione a uno stream. Puoi aprire più connessioni nello stream predefinito. Questi aggiunte sono asincrone,
il che ti consente di inviare contemporaneamente una serie di scritture. I messaggi di risposta su ogni connessione bidirezionale arrivano nello stesso ordine in cui sono state inviate le richieste.
Gli stream creati dall'applicazione possono avere una sola connessione attiva. Come best practice, limita il numero di connessioni attive, e utilizza una connessione per il maggior numero possibile di scritture di dati. Quando utilizzi lo stream predefinito in Java o Go, puoi utilizzare il multiplexing dell'API Storage Write per scrivere in più tabelle di destinazione con connessioni condivise.
In genere, una singola connessione supporta almeno 1 MBps di throughput. Il valore superiore dipende da diversi fattori, come la larghezza di banda della rete, lo schema dei dati e il carico del server. Quando una connessione raggiunge il limite di throughput, le richieste in entrata potrebbero essere rifiutate o messe in coda finché il numero di richieste in corso non diminuisce. Se hai bisogno di una maggiore velocità in uscita, crea più connessioni.
BigQuery chiude la connessione gRPC se rimane inattiva per troppo tempo. In questo caso, il codice di risposta è HTTP 409
. La connessione gRPC può essere chiusa anche in caso di riavvio del server o per altri motivi. Se si verifica un errore di connessione, crea una nuova connessione. Le librerie client Java e Go si ricollegano automaticamente se la connessione viene chiusa.
Supporto della libreria client
Esistono librerie client per l'API Storage Write in più linguaggi di programmazione ed espongono i costrutti dell'API basata su gRPC sottostante. Questa API sfrutta funzionalità avanzate come lo streaming bidirezionale, che potrebbe richiedere un ulteriore lavoro di sviluppo per il supporto. A tal fine, per questa API sono disponibili una serie di astrazioni di livello superiore che semplificano queste interazioni e riducono i problemi degli sviluppatori. Ti consigliamo di utilizzare queste altre astrattizioni della libreria, se possibile.
Questa sezione fornisce ulteriori dettagli sui linguaggi e sulle librerie in cui sono state fornite agli sviluppatori funzionalità aggiuntive rispetto all'API generata.
Per visualizzare esempi di codice relativi all'API Storage Write, visita questa pagina.
Client Java
La libreria client Java fornisce due oggetti writer:
StreamWriter
: accetta i dati in formato buffer di protocollo.JsonStreamWriter
: accetta i dati in formato JSON e li converte in buffer del protocollo prima di inviarli tramite rete.JsonStreamWriter
supporta anche gli aggiornamenti automatici dello schema. Se lo schema della tabella cambia, lo scrittore si ricollega automaticamente al nuovo schema, consentendo al client di inviare i dati utilizzando il nuovo schema.
Il modello di programmazione è simile per entrambi gli autori. La differenza principale è il modo in cui formatti il payload.
L'oggetto writer gestisce una connessione all'API Storage Write. L'oggetto writer pulizia automatica delle richieste, aggiunge le intestazioni di instradamento regionale alle richieste e si ricollega dopo errori di connessione. Se utilizzi direttamente l'API gRPC, devi gestire questi dettagli.
Client Go
Il client Go utilizza un'architettura client-server per codificare i messaggi nel formato Protocol Buffer utilizzando proto2. Consulta la documentazione di Go per informazioni dettagliate su come utilizzare il client Go, con codice di esempio.
Client Python
Il client Python è un client di livello inferiore che racchiude l'API gRPC. Per utilizzare questo client, devi inviare i dati come buffer di protocollo, seguendo il flusso dell'API per il tipo specificato.
Evita di utilizzare la generazione di messaggi proto dinamici in Python perché le prestazioni della libreria non sono adeguate.
Per scoprire di più sull'utilizzo dei buffer di protocollo con Python, leggi il tutorial sulle nozioni di base dei buffer di protocollo in Python.
Client Node.js
La libreria client NodeJS accetta input JSON e fornisce il supporto per il ricoinvolgimento automatico. Per informazioni dettagliate su come utilizzare il client, consulta la documentazione.
Conversioni dei tipi di dati
La tabella seguente mostra i tipi di buffer del protocollo supportati per ogni tipo di dati BigQuery:
Tipo di dati BigQuery | Tipi di buffer di protocollo supportati |
---|---|
BOOL |
bool , int32 , int64 ,
uint32 , uint64 , google.protobuf.BoolValue |
BYTES |
bytes , string , google.protobuf.BytesValue |
DATE |
int32 (opzione preferita), int64 , string
Il valore è il numero di giorni dall'epoca Unix (1970-01-01). L' intervallo valido è compreso tra "-719162" (0001-01-01) e "2932896" (9999-12-31). |
DATETIME , TIME |
string
|
int64
Utilizza la classe
|
|
FLOAT |
double , float , google.protobuf.DoubleValue , google.protobuf.FloatValue |
GEOGRAPHY |
string
Il valore è una geometria in formato WKT o GeoJson. |
INTEGER |
int32 , int64 , uint32 ,
enum , google.protobuf.Int32Value ,
google.protobuf.Int64Value ,
google.protobuf.UInt32Value |
JSON |
string |
NUMERIC , BIGNUMERIC |
int32 , int64 , uint32 ,
uint64 , double , float ,
string |
bytes , google.protobuf.BytesValue Utilizza la classe
|
|
STRING |
string , enum , google.protobuf.StringValue |
TIME |
string
Il valore deve essere un
letterale |
TIMESTAMP |
int64 (opzione preferita), int32 ,
uint32 , google.protobuf.Timestamp
Il valore è espresso in microsecondi dall'epoca Unix (01/01/1970). |
INTERVAL |
string , google.protobuf.Duration
Il valore della stringa deve essere un
letterale |
RANGE<T> |
message
Un tipo di messaggio nidificato nel proto con due campi,
|
REPEATED FIELD |
array
Un tipo di array nel proto corrisponde a un campo ripetuto in BigQuery. |
RECORD |
message
Un tipo di messaggio nidificato nel proto corrisponde a un campo del record in BigQuery. |
Gestire la mancata disponibilità
La ripetizione dei tentativi con backoff esponenziale può attenuare gli errori casuali e brevi periodi di mancata disponibilità del servizio, ma per evitare di eliminare righe durante periodi di mancata disponibilità prolungati è necessario un approccio più ponderato. In particolare, se un client non riesce a inserire una riga in modo persistente, che cosa deve fare?
La risposta dipende dai tuoi requisiti. Ad esempio, se BigQuery viene utilizzato per l'analisi operativa in cui alcune righe mancanti sono accettabili, il client può rinunciare dopo alcuni tentativi e ignorare i dati. Se invece ogni riga è fondamentale per l'attività, ad esempio per i dati finanziari, devi avere una strategia per mantenere i dati fino a quando non possono essere inseriti in un secondo momento.
Un modo comune per gestire gli errori persistenti è pubblicare le righe in un argomento Pub/Sub per la valutazione e l'eventuale inserimento futuri. Un altro metodo comune è la persistenza temporanea dei dati sul client. Entrambi i metodi possono mantenere i client sbloccati e, al contempo, garantire che tutte le righe possano essere inserite una volta ripristinata la disponibilità.
Partizionamento delle colonne per unità di tempo
Puoi eseguire lo streaming dei dati in una tabella partizionata in base a una colonna DATE
, DATETIME
o
TIMESTAMP
compresa tra 5 anni nel passato e 1 anno nel futuro.
I dati al di fuori di questo intervallo vengono rifiutati.
Quando i dati vengono trasmessi in streaming, vengono inizialmente inseriti nella partizione __UNPARTITIONED__
. Dopo aver raccolto dati non partizionati sufficienti, BigQuery li ripartisce nella partizione appropriata.
Tuttavia, non esiste un accordo sul livello del servizio (SLA) che definisce il tempo necessario per il trasferimento dei dati dalla partizione __UNPARTITIONED__
.
L'API Storage Write non supporta l'uso di decoratori della partizione.
Plug-in di output dell'API Storage Write di Fluent Bit
Il plug-in di output dell'API Storage Write di Fluent Bit automatizza il processo di importazione dei record JSON in BigQuery, eliminando la necessità di scrivere codice. Con questo plug-in, devi solo configurare un plug-in di input compatibile e impostare un file di configurazione per iniziare a eseguire lo streaming dei dati. Fluent Bit è un elaboratore e inoltro di log open source e cross-platform che utilizza plug-in di input e output per gestire diversi tipi di origini dati e sink.
Questo plug-in supporta quanto segue:
- Semantika almeno una volta utilizzando il tipo predefinito.
- Semantika esattamente una volta utilizzando il tipo di commit.
- Scalabilità dinamica per gli stream predefiniti, quando è indicata la contropressione.
Metriche del progetto dell'API Storage Write
Per le metriche per monitorare l'importazione dati con l'API Storage Write, ad esempio la latenza a livello di richiesta lato server, le connessioni simultanee, i byte caricati e le righe caricate, consulta le metriche di Google Cloud.
Utilizzare data manipulation language (DML) con i dati sottoposti a streaming di recente
Puoi utilizzare data manipulation language (DML), ad esempio gli statement UPDATE
, DELETE
o
MERGE
, per modificare le righe scritte di recente in una tabella BigQuery
dall'API BigQuery Storage Write. Le scritture recenti sono quelle che si sono verificate
gli ultimi 30 minuti.
Per ulteriori informazioni sull'utilizzo di DML per modificare i dati in streaming, consulta Utilizzare il linguaggio di manipolazione dei dati.
Limitazioni
- Il supporto per l'esecuzione di istruzioni DML con modifica sui dati sottoposti a streaming di recente non si estende ai dati sottoposti a streaming utilizzando l'API BigQuery Storage Write di tipo buffered
- Il supporto per l'esecuzione di istruzioni DML con mutazioni sui dati sottoposti a streaming di recente non si estende ai dati sottoposti a streaming utilizzando l'API insertAll streaming.
- L'esecuzione di istruzioni DML con mutazioni all'interno di una transazione con più istruzioni in base ai dati sottoposti a streaming di recente non è supportata.
Quote dell'API Storage Write
Per informazioni su quote e limiti dell'API Storage Write, consulta Quote e limiti dell'API BigQuery Storage Write.
Puoi monitorare l'utilizzo delle quote relative a connessioni simultanee e throughput nella pagina Quote della console Google Cloud.
Calcolare la velocità effettiva
Supponiamo che il tuo obiettivo sia raccogliere i log da 100 milioni di endpoint
creando 1500 record di log al minuto. Poi puoi stimare il throughput come
100 million * 1,500 / 60 seconds = 2.5 GB per second
.
Devi assicurarti in anticipo di disporre di una quota adeguata per gestire questo throughput.
Prezzi dell'API Storage Write
Per i prezzi, consulta Prezzi dell'importazione dati.
Caso d'uso di esempio
Supponiamo che esista una pipeline che elabora i dati sugli eventi dai log degli endpoint. Gli eventi vengono generati continuamente e devono essere disponibili per le query in BigQuery il prima possibile. Poiché l'aggiornamento dei dati è fondamentale per questo caso d'uso, l'API Storage Write è la scelta migliore per importare i dati in BigQuery. Un'architettura consigliata per mantenere questi endpoint essenziali è l'invio di eventi a Pub/Sub, da dove vengono utilizzati da una pipeline Dataflow in modalità flusso che trasmette direttamente in BigQuery.
Un problema di affidabilità principale per questa architettura è come gestire l'errore di inserimento di un record in BigQuery. Se ogni record è importante e non può essere perso, i dati devono essere memorizzati nella memoria prima di tentare l'inserimento. Nell'architettura consigliata sopra, Pub/Sub può svolgere il ruolo di un buffer con le sue funzionalità di conservazione dei messaggi. La pipeline Dataflow deve essere configurata per riprovare gli inserimenti in streaming di BigQuery con backoff esponenziale troncato. Una volta esaurita la capacità di Pub/Sub come buffer, ad esempio in caso di indisponibilità prolungata di BigQuery o di un errore di rete, i dati devono essere mantenuti nel client e il client deve disporre di un meccanismo per riprendere l'inserimento dei record permanenti una volta ripristinata la disponibilità. Per ulteriori informazioni su come gestire questa situazione, consulta il post del blog Guida all'affidabilità di Google Pub/Sub.
Un altro caso di errore da gestire è quello di un record dannoso. Un record dannoso è un record rifiutato da BigQuery perché non è stato inserito con un errore non ripetibile o un record che non è stato inserito correttamente dopo il numero massimo di tentativi. Entrambi i tipi di record devono essere memorizzati in una "coda di messaggi non recapitati" dalla pipeline di Dataflow per ulteriori accertamenti.
Se sono necessarie le semantiche di esecuzione esattamente una volta, crea uno stream di scrittura in tipo di commit con gli offset dei record forniti dal client. In questo modo vengono evitati i duplicati, poiché l'operazione di scrittura viene eseguita solo se il valore dell'offset corrisponde all'offset di accodamento successivo. Se non fornisci un offset, i record vengono aggiunti alla fine corrente dello stream e la ripetizione di un'aggiunta non riuscita potrebbe comportare la visualizzazione del record più di una volta nello stream.
Se non sono richieste garanzie di esecuzione esattamente una volta, la scrittura nello stream predefinito consente un throughput più elevato e non viene conteggiata ai fini del limite di quota per la creazione di stream di scrittura.
Stima il throughput della tua rete e assicurati in anticipo di disporre di una quota adeguata per gestire il throughput.
Se il tuo carico di lavoro genera o elabora dati a una frequenza molto irregolare, prova a smussare gli eventuali picchi di carico sul client e a trasmettere in streaming in BigQuery con un throughput costante. In questo modo puoi semplificare la pianificazione delle capacità. Se non è possibile, assicurati di essere pronto a gestire gli errori 429
(risorsa esaurita) se e quando il tuo throughput supera la quota durante picchi brevi.
Passaggi successivi
- Eseguire lo streaming dei dati utilizzando l'API Storage Write
- Caricare i dati in blocco utilizzando l'API Storage Write
- Best practice per l'API Storage Write