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 aiutarti a comprendere in modo approfondito 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 client di ascoltare gli aggiornamenti dei dati in tempo reale. Puoi usare gli aggiornamenti in tempo reale per creare app adattabili che non richiedono l'infrastruttura del server. Sebbene sia molto facile avviare e utilizzare qualcosa, è utile comprendere i vincoli dei sistemi che compongono Firestore in modo che la tua app serverless possa scalare e avere un buon rendimento quando il traffico aumenta.

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

Scegli una posizione 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 connessione a Firestore, la connessione viene indirizzata a un server frontend Firestore nella stessa regione 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 Firestore la posizione del database influisce sulla latenza sperimentata 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:

Attivare la modalità offline

Gli SDK Firebase forniscono la persistenza dei dati offline. Se l'app sul dispositivo dell'utente non riesce a connettersi a Firestore, l'app rimane utilizzabile lavorando con dati memorizzati nella cache locale. Questo assicura che i dati l'accesso anche quando la connessione a internet è instabile o 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 è possibile aggirare gli errori temporanei causati riavviando i server o causando problemi di rete tra il client per configurare un database.

Scegliere tra località regionali e multiregionali

Ci sono diversi compromessi nella scelta tra regionale e località multiregionali. La differenza principale è il modo in cui i dati vengono replicati. In questo modo, viene migliorata la disponibilità della tua app. Un'istanza multiregione offre una maggiore affidabilità di pubblicazione e aumenta la durabilità dei dati, ma il costo è maggiore.

Comprendere il sistema di query in tempo reale

Le query in tempo reale, chiamate anche ascoltatori di snapshot, consentono all'app di ascoltare le modifiche nel database e di ricevere notifiche a bassa latenza non appena i dati subiscono 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 su come configurare e utilizzare le query in tempo reale, consulta Ricevere aggiornamenti in tempo reale. Le sezioni seguenti illustrano in dettaglio il funzionamento degli ascoltatori di istantanee e descrivono alcune delle best practice per scalare le query in tempo reale mantenendo le prestazioni.

Immagina due utenti che si connettono a Firestore tramite un'app di messaggistica creata con uno degli SDK mobile.

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 un ascoltatore di snapshot al database, si verifica la seguente sequenza di eventi:

  1. Il client B apre una connessione a Firestore e registra un ascoltatore effettuando una chiamata a onSnapshot(collection("chatroom")) tramite l'SDK Firebase. Questo ascoltatore può rimanere attivo per ore.
  2. Il frontend di Firestore esegue query sul sistema di archiviazione sottostante eseguire il bootstrap del set di dati. Carica l'intero set di risultati documenti. Questo tipo di query viene chiamato query di polling. Il sistema poi valuta le regole di sicurezza Firebase del database 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 alla modalità di ascolto. L'ascoltatore si 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, distribuisce i dati aggiornati a un pool di gestori di iscrizioni.
  8. Viene eseguito un corrispondenza di query inversa per verificare se il documento aggiornato corrisponde a eventuali listener di istantanee attualmente registrati. In questo esempio, il documento corrisponde al listener snapshot del Client B. Come suggerisce il nome, puoi considerare il correlatore di query inversa come una normale query sul database, ma eseguita in modo inverso. 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 agli ascoltatori degli snapshot. Il sistema valuta quindi le regole di sicurezza di Firebase del database per assicurarsi 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 è attivata, l'SDK 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 gestire milioni di query in tempo reale e utenti connessi. Eseguendo molte repliche di tutti questi componenti su più zone (o più regioni nel caso di un deployment multiregionale), Firestore raggiunge un'alta disponibilità e scalabilità.

È importante notare che tutte le operazioni di lettura emesse dagli SDK mobile e web seguono il modello riportato sopra. Esegue una query di polling seguita dalla modalità di ascolto per mantenere le garanzie di coerenza. Questo vale anche per gli ascoltatori 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.

Informazioni sul 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. Quando la frequenza di scrittura per un database aumenta oltre il limite che un singolo server può gestire, il log delle modifiche viene suddiviso su più server e l'elaborazione delle query inizia a consumare i dati di più gestori degli abbonamenti anziché uno. Da dal punto di vista del client e dell'SDK, è tutto trasparente e non è richiesta alcuna azione dall'app quando si verificano le suddivisioni. Il seguente diagramma mostra come la scalabilità delle query in tempo reale:

Architettura del fan-out del log delle modifiche

La scalabilità automatica ti consente di aumentare il traffico di scrittura senza limiti, ma con l'aumento del traffico, 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 agli ascoltatori attualmente registrati. 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. Ciò semplifica lo sviluppo dell'app rimuovendo i casi limite legati 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.

Mantieni i documenti e le operazioni di scrittura di piccole dimensioni

Quando crei app con listener di snapshot, in genere vuoi che gli utenti trovino rapidamente i cambiamenti nei dati. Per farlo, cerca di mantenere le cose semplici. Il sistema può inviare piccoli documenti con decine di campi molto 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.

Utilizzare 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 la tua app memorizza la maggior parte dei dati in una raccolta di grandi dimensioni, l'ascoltatore potrebbe dover connettersi a molti server per ricevere tutti i dati di cui ha bisogno. Questo vale anche se applichi un filtro alla 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 essere meglio suddividere i dati in raccolte più piccole con tassi di scrittura inferiori.

È simile al pensare alle query sul rendimento in un database relazionale che richiedono scansioni complete della tabella. In un database relazionale, una query che richiede una scansione completa della tabella è l'equivalente di un ascoltatore di snapshot che monitora una raccolta con un elevato tasso di turnover. L'esecuzione potrebbe essere lenta rispetto a una query che il database può eseguire utilizzando un indice più specifico. Una query con un indice più specifico è come un ascoltatore di snapshot che monitora un singolo documento o una raccolta che cambia meno spesso. Devi eseguire il test di caricamento della tua app per comprendere meglio il comportamento e le esigenze del tuo caso d'uso.

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.

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

  • Il sistema riequilibra un log delle modifiche a causa di variazioni del carico.
  • Gli hotspot causano scritture non riuscite o ritardate sul database.
  • I riavvii temporanei del server influiscono temporaneamente sugli ascoltatori.

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

Favorire gli ascoltatori di lunga durata

Aprire e mantenere attivi gli ascoltatori il più a lungo possibile è spesso il modo più economico 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 di snapshot a lunga durata legge e solo i dati necessari per eseguire la query per tutta la durata del ciclo di vita. 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.

Se la tua app deve consumare una frequenza elevata di dati, gli ascoltatori di snapshot potrebbero non essere appropriati. Ad esempio, se il tuo caso d'uso invia molti documenti al secondo tramite una connessione per un periodo di tempo prolungato, potrebbe essere meglio optare per query una tantum eseguite a una frequenza inferiore.

Passaggi successivi