Comprendi le query in tempo reale su larga scala

Leggi questo documento per indicazioni su come scalare la tua app serverless oltre le migliaia di operazioni al secondo o centinaia di migliaia di utenti in contemporanea. Questo documento include argomenti avanzati per aiutare conoscere in dettaglio il sistema. Se stai iniziando Consulta la guida rapida per Firestore.

Firestore e gli SDK Firebase web/mobile forniscono un modello efficace per lo sviluppo di app serverless in cui il codice lato client accede direttamente per configurare un database. Gli SDK consentono ai clienti di ascoltare gli aggiornamenti dei dati in tempo reale. Tu Puoi utilizzare gli aggiornamenti in tempo reale per creare app adattabili che non richiedono server dell'infrastruttura. Sebbene sia molto facile configurare qualcosa, aiuta per comprendere i vincoli nei sistemi che compongono Firestore in modo che la tua app serverless scala e funzioni bene quando il traffico aumenta.

Consulta le sezioni seguenti per consigli sulla scalabilità della tua app.

Scegli una località del database vicina agli utenti

Il seguente diagramma illustra l'architettura di un'app in tempo reale:

Esempio di architettura delle app in tempo reale

Quando un'app in esecuzione sul dispositivo di un utente (mobile o web) stabilisce una a Firestore, la connessione viene instradata a un server frontend Firestore nello stesso region in cui si trova il database. Ad esempio: Se il database è in us-east1, la connessione viene trasferita anche a un Frontend di Firestore anche in us-east1. Queste connessioni sono di lunga durata e rimangono aperte finché non vengono chiuse esplicitamente dall'app. Il frontend legge i dati dai sistemi di archiviazione Firestore sottostanti.

La distanza tra la posizione fisica di un utente e la posizione del database Firestore influisce sulla latenza riscontrata dall'utente. Ad esempio, un utente in India la cui app comunica con un database in una regione Google Cloud in Nord America potrebbe trovare l'esperienza più lenta e l'app meno rapida rispetto a quando il database era invece più vicina, come in India o in un'altra parte dell'Asia.

Progettazione per l'affidabilità

I seguenti argomenti migliorano o influiscono sull'affidabilità della tua app:

Abilita modalità offline

Gli SDK Firebase forniscono la persistenza dei dati offline. Se l'app sul dispositivo dell'utente non riesce a connettersi a Firestore, rimane utilizzabile lavorando con i dati memorizzati nella cache locale. In questo modo, gli utenti possono accedere ai dati anche quando la connessione a internet è intermittente o quando perdono completamente l'accesso per diverse ore o giorni. Per ulteriori dettagli su modalità offline, consulta l'articolo Attivare i dati offline.

Informazioni sui nuovi tentativi automatici

Gli SDK Firebase si occupano di ritentare le operazioni e ristabilire connessioni interrotte. In questo modo puoi aggirare gli errori temporanei causati dall'riavvio dei server o da problemi di rete tra il client e il database.

Scegli tra località a singola regione e a più regioni

Ci sono diversi compromessi nella scelta tra regionale e località multiregionali. La differenza principale è il modo in cui i dati vengono replicati. Questo determina la disponibilità garantita della tua app. Un'istanza multiregionale offre una maggiore affidabilità di servizio e aumenta la durabilità dei dati, il compromesso è il costo.

Informazioni sul sistema di query in tempo reale

Le query in tempo reale, chiamate anche listener di snapshot, consentono all'app di ascoltare modifiche nel database e ricevi notifiche a bassa latenza non appena i dati modifiche. Un'app può ottenere lo stesso risultato eseguendo periodicamente il polling del database per ma spesso è più lento, più costoso e richiede più codice. Per esempi di come impostare e utilizzare query in tempo reale, vedi Ricevi aggiornamenti in tempo reale. Le seguenti sezioni entrare nel dettaglio del funzionamento dei listener di snapshot e descrivere alcune delle best practice per scalare le query in tempo reale senza rinunciare alle prestazioni.

Immagina due utenti che si connettono a Firestore tramite un creata con uno degli SDK per dispositivi mobili.

Il client A scrive nel database per aggiungere e aggiornare i documenti in una raccolta chiamata chatroom:

collection chatroom:
    document message1:
      from: 'Sparky'
      message: 'Welcome to Firestore!'

    document message2:
      from: 'Santa'
      message: 'Presents are coming'

Il client B rimane in ascolto degli aggiornamenti nella stessa raccolta utilizzando un listener snapshot. Il cliente B riceve una notifica immediata ogni volta che qualcuno crea un nuovo messaggio. Il seguente diagramma mostra l'architettura alla base di un listener di snapshot:

Architettura di una connessione listener di snapshot

Quando il client B connette uno snapshot, si verifica la seguente sequenza di eventi listener per il database:

  1. Il client B apre una connessione a Firestore e registra una ascoltatore effettuando una chiamata a onSnapshot(collection("chatroom")) tramite l'SDK Firebase. Questo listener può rimanere attivo per ore.
  2. Il frontend di Firestore esegue query sul sistema di archiviazione sottostante per avviare il set di dati. Carica l'intero set di risultati dei documenti corrispondenti. Si tratta di una query di polling. Il sistema valuta i valori Regole di sicurezza di Firebase per verificare che l'utente possa accedere a questi dati. Se l'utente è autorizzato, restituisce i dati all'utente.
  3. La query del client B passa quindi in modalità di ascolto. Il listener registra con un gestore degli abbonamenti e attende gli aggiornamenti dei dati.
  4. Il client A ora invia un'operazione di scrittura per modificare un documento.
  5. Il database esegue il commit della modifica del documento nel suo sistema di archiviazione.
  6. A livello transazionale, il sistema esegue il commit dello stesso aggiornamento in una changelog. Il log delle modifiche stabilisce un ordine rigoroso delle modifiche, quando accadono.
  7. Il log delle modifiche a sua volta trasferisce i dati aggiornati a un pool di iscrizioni e i gestori di rete.
  8. Viene eseguito un matcher inversa delle query per verificare se il documento aggiornato corrisponde listener di snapshot attualmente registrati. In questo esempio, il documento corrisponde al listener snapshot del Client B. Come suggerisce il nome, puoi pensare il matcher inverso come una normale query di database, ma al contrario. Anziché cercare tra i documenti per trovare quelli che corrispondono a una query, cerca in modo efficiente per trovare quelle che corrispondono a un documento in arrivo. Una volta trovata una corrispondenza, il sistema inoltra il documento in questione ai listener snapshot. Quindi il sistema valuta le regole di sicurezza di Firebase del database. per garantire che solo gli utenti autorizzati ricevano i dati.
  9. Il sistema inoltra l'aggiornamento del documento all'SDK sul dispositivo del cliente B e viene attivato il callback onSnapshot. Se la persistenza locale è abilitata, l'SDK e applica l'aggiornamento anche alla cache locale.

Una parte fondamentale della scalabilità di Firestore dipende dal fan-out da il log delle modifiche ai gestori delle sottoscrizioni e ai server frontend. La distribuzione consente a una singola modifica dei dati di propagarsi in modo efficiente per soddisfare milioni di query in tempo reale e utenti connessi. Eseguendo molte repliche di tutti questi in più zone (o più regioni nel caso di più regioni del deployment), Firestore raggiunge disponibilità e scalabilità elevate.

Vale la pena notare che tutte le operazioni di lettura eseguite da SDK web e per dispositivi mobili segui il modello riportato sopra. Esegue una query di polling seguita dalla modalità di ascolto per mantenere le garanzie di coerenza. Questo vale anche per chi ascolta in tempo reale, per recuperare un documento e query one-shot. Puoi pensare a singole i recuperi di documenti e le query one-shot come listener di snapshot di breve durata che presentano vincoli simili in termini di rendimento.

Applica le best practice per scalare le query in tempo reale

Applica le seguenti best practice per progettare query scalabili in tempo reale.

Comprendi il traffico di scrittura elevato nel sistema

Questa sezione ti aiuta a capire come il sistema risponde a una domanda sempre maggiore di richieste di scrittura.

Log delle modifiche di Firestore che generano le query in tempo reale scalare automaticamente orizzontalmente all'aumento del traffico in scrittura. Come velocità di scrittura per un database va oltre la capacità di gestione di un singolo server, il log delle modifiche è suddiviso tra più server e l'elaborazione delle query inizia e consumano i dati di più gestori di abbonamenti invece che uno. Da dal punto di vista del client e dell'SDK, è tutto trasparente e non è richiesta alcuna azione dall'app in caso di suddivisione. Il seguente diagramma mostra come vengono scalate le query in tempo reale:

Architettura del fan-out del log delle modifiche

La scalabilità automatica consente di aumentare il traffico di scrittura senza limiti, ma man mano che il traffico aumenta, il sistema potrebbe impiegare un po' di tempo per rispondere. Segui i consigli della regola 5-5-5 per evitare di creare un hotspot di scrittura. Key Visualizer è una uno strumento utile per analizzare gli hotspot di scrittura.

Molte app hanno una crescita organica prevedibile, che Firestore può gestire senza precauzioni. per carichi di lavoro in batch, del set di dati, tuttavia, può aumentare le scritture troppo rapidamente. Mentre progetti la tua app, della provenienza del traffico di scrittura.

Informazioni sulle interazioni tra scritture e letture

Puoi pensare al sistema di query in tempo reale come a una pipeline che collega la scrittura operazioni con i lettori. Ogni volta che un documento viene creato, aggiornato o eliminato la modifica si propaga dal sistema di archiviazione a quello attualmente registrato e ascoltatori. La struttura del log delle modifiche di Firestore con coerenza, vale a dire che la tua app non riceve mai notifiche aggiornamenti non in ordine rispetto a quando il database ha eseguito il commit dei dati modifiche. In questo modo, lo sviluppo delle app viene semplificato rimuovendo i casi limite relativi alla coerenza dei dati.

Questa pipeline collegata significa che un'operazione di scrittura che causa hotspot o contese per i blocchi può influire negativamente sulle operazioni di lettura. Quando le operazioni di scrittura non riescono o sono limitate, la lettura in attesa di dati coerenti dal log delle modifiche. Se questo si verifica della tua app, potresti vedere operazioni di scrittura lente e una risposta lenta correlata volte per le query. Evitare gli hotspot è fondamentale per evitare problema.

Riduci i documenti e le operazioni di scrittura

Quando crei app con listener di snapshot, in genere vuoi che gli utenti trovino rapidamente i cambiamenti nei dati. Per raggiungere questo obiettivo, cerca di limitare le cose. La può eseguire il push di piccoli documenti con decine di campi attraverso il sistema rapidamente. Documenti di grandi dimensioni con centinaia di campi e dati di grandi dimensioni richiedono più tempo da elaborare.

Allo stesso modo, favorisci operazioni di commit e scrittura brevi e veloci per mantenere bassa la latenza. I batch di grandi dimensioni potrebbero offrire una velocità effettiva più elevata dal punto di vista dell'autore ma potrebbe effettivamente aumentare il tempo di notifica per i listener di snapshot. Spesso questo approccio è controintuitivo rispetto all'utilizzo di altri sistemi di database in cui potresti utilizzare il batching per migliorare le prestazioni.

Utilizza listener efficienti

Con l'aumento della velocità di scrittura del database, Firestore suddivide l'elaborazione dei dati tra più server. L'algoritmo di sharding di Firestore tenta di co-posizionare i dati la stessa raccolta o lo stesso gruppo di raccolte sullo stesso server di log delle modifiche. La di sistema cerca di massimizzare la possibile velocità effettiva di scrittura, conservando al contempo il numero il più basso possibile di server coinvolti nell'elaborazione di una query.

Tuttavia, alcuni pattern potrebbero comunque portare a un comportamento non ottimale per lo snapshot e ascoltatori. Ad esempio, se l'app archivia la maggior parte dei dati in un ambiente raccolta, il listener potrebbe dover connettersi a più server per ricevere di cui ha bisogno. Questo vale anche se applichi un filtro di query. Connessione in corso... a molti server aumenta il rischio di risposte più lente.

Per evitare queste risposte più lente, progetta lo schema e l'app in modo che il sistema può gestire i listener senza passare per molti server diversi. Potrebbe funzionare è preferibile suddividere i dati in raccolte più piccole con velocità di scrittura inferiori.

È un po' come pensare alle query sulle prestazioni in un database relazionale che richiede scansioni complete delle tabelle. In un contesto relazionale, un database, una query che richiede una scansione completa della tabella è l'equivalente di listener di snapshot che monitora una raccolta con un tasso di abbandono elevato. Potrebbe funzionare lentamente rispetto a una query che il database può gestire usando un indice più specifico. Una query con un indice più specifico è come un listener di snapshot che controlla un documento singolo o una raccolta che cambia con minore frequenza. Dovresti caricare testare l'app per comprenderne al meglio il comportamento e le esigenze.

Fai in modo che le query di polling siano rapide

Un'altra parte fondamentale delle query adattabili in tempo reale è assicurarsi che la query di polling per il bootstrap dei dati è veloce ed efficiente. La prima volta che un nuovo ascoltatore di istantanee si connette, deve caricare l'intero insieme di risultati e inviarlo al dispositivo dell'utente. Le query lente rendono la tua app meno reattiva. Sono incluse, ad esempio, query a leggere molti documenti o query che non usano gli indici appropriati.

Un listener potrebbe anche passare da uno stato di ascolto a uno stato di polling in in alcune circostanze. Ciò avviene automaticamente ed è trasparente per SDK e la tua app. Le seguenti condizioni potrebbero attivare uno stato di polling:

  • Il sistema ribilancia un log delle modifiche a causa delle modifiche al carico.
  • Gli hotspot causano scritture non riuscite o ritardate sul database.
  • I riavvii temporanei del server influiscono temporaneamente sui listener.

Se le query di polling sono abbastanza veloci, lo stato di sondaggio diventa trasparente agli utenti della tua app.

Prediligi gli ascoltatori di lunga durata

Avviare e mantenere vivi gli ascoltatori il più a lungo possibile è spesso la un modo conveniente per creare un'app che utilizza Firestore. Quando si utilizza Firestore, ti verranno addebitati i documenti restituiti alla tua app e non per mantenere una connessione aperta. Un listener snapshot di lunga durata legge solo i dati di cui ha bisogno per eseguire la query per tutta la sua durata. Ciò include un'operazione di polling iniziale seguita da notifiche quando i dati cambiano effettivamente. Le query one-shot, invece, rileggono i dati che potrebbero non sono stati modificati dall'ultima volta che l'app ha eseguito la query.

Nei casi in cui la tua app deve utilizzare una quantità elevata di dati, i listener di snapshot potrebbe non essere appropriato. Ad esempio, se il tuo caso d'uso esegue il push di molti documenti al secondo tramite una connessione per un periodo di tempo prolungato, è preferibile optare per query one-shot che vengono eseguite con una frequenza inferiore.

Passaggi successivi