Comprender las consultas en tiempo real a escala

Lea este documento para obtener orientación sobre cómo escalar su aplicación sin servidor más allá de miles de operaciones por segundo o cientos de miles de usuarios simultáneos. Este documento incluye temas avanzados para ayudarle a comprender el sistema en profundidad. Si recién estás comenzando con Cloud Firestore, consulta la guía de inicio rápido .

Cloud Firestore y los SDK web/móvil de Firebase proporcionan un modelo potente para desarrollar aplicaciones sin servidor donde el código del lado del cliente accede directamente a la base de datos. Los SDK permiten a los clientes escuchar las actualizaciones de los datos en tiempo real. Puede utilizar actualizaciones en tiempo real para crear aplicaciones responsivas que no requieran infraestructura de servidor. Si bien es muy fácil poner algo en funcionamiento, es útil comprender las limitaciones de los sistemas que componen Cloud Firestore para que su aplicación sin servidor escale y funcione bien cuando aumenta el tráfico.

Consulte las siguientes secciones para obtener consejos sobre cómo escalar su aplicación.

Elija una ubicación de base de datos cercana a sus usuarios

El siguiente diagrama demuestra la arquitectura de una aplicación en tiempo real:

Ejemplo de arquitectura de aplicación en tiempo real

Cuando una aplicación que se ejecuta en el dispositivo de un usuario (móvil o web) establece una conexión con Cloud Firestore, la conexión se enruta a un servidor frontend de Cloud Firestore en la misma región donde se encuentra su base de datos. Por ejemplo, si su base de datos está en us-east1 , la conexión también va a una interfaz de Cloud Firestore también en us-east1 . Estas conexiones son duraderas y permanecen abiertas hasta que la aplicación las cierra explícitamente. La interfaz lee datos de los sistemas de almacenamiento subyacentes de Cloud Firestore.

La distancia entre la ubicación física de un usuario y la ubicación de la base de datos de Cloud Firestore afecta la latencia que experimenta el usuario. Por ejemplo, un usuario de la India cuya aplicación se comunica con una base de datos en una región de Google Cloud en América del Norte podría encontrar la experiencia más lenta y la aplicación menos ágil que si la base de datos estuviera ubicada más cerca, como en la India o en otra parte de Asia. .

Diseño para la confiabilidad

Los siguientes temas mejoran o afectan la confiabilidad de su aplicación:

Habilitar el modo fuera de línea

Los SDK de Firebase brindan persistencia de datos sin conexión. Si la aplicación en el dispositivo del usuario no puede conectarse a Cloud Firestore, la aplicación sigue siendo utilizable al trabajar con datos almacenados en caché local. Esto garantiza el acceso a los datos incluso cuando los usuarios experimentan conexiones a Internet irregulares o pierden completamente el acceso durante varias horas o días. Para obtener más detalles sobre el modo sin conexión, consulte Habilitar datos sin conexión .

Comprender los reintentos automáticos

Los SDK de Firebase se encargan de reintentar operaciones y restablecer conexiones rotas. Esto ayuda a solucionar errores transitorios causados ​​por el reinicio de servidores o problemas de red entre el cliente y la base de datos.

Elija entre ubicaciones regionales y multirregionales

Existen varias compensaciones al elegir entre ubicaciones regionales y multirregionales. La principal diferencia es cómo se replican los datos. Esto impulsa las garantías de disponibilidad de su aplicación. Una instancia multirregional brinda mayor confiabilidad en el servicio y aumenta la durabilidad de sus datos, pero la contrapartida es el costo.

Comprender el sistema de consultas en tiempo real

Las consultas en tiempo real, también llamadas escuchas de instantáneas, permiten que la aplicación escuche los cambios en la base de datos y reciba notificaciones de baja latencia tan pronto como cambien los datos. Una aplicación puede obtener el mismo resultado sondeando periódicamente la base de datos en busca de actualizaciones, pero suele ser más lenta, más costosa y requiere más código. Para ver ejemplos de cómo configurar y utilizar consultas en tiempo real, consulte Obtener actualizaciones en tiempo real . Las siguientes secciones detallan cómo funcionan los oyentes de instantáneas y describen algunas de las mejores prácticas para escalar consultas en tiempo real manteniendo el rendimiento.

Imagine dos usuarios que se conectan a Cloud Firestore a través de una aplicación de mensajería creada con uno de los SDK móviles.

El cliente A escribe en la base de datos para agregar y actualizar documentos en una colección llamada chatroom :

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

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

El cliente B escucha actualizaciones en la misma colección mediante un detector de instantáneas. El cliente B recibe una notificación inmediata cada vez que alguien crea un mensaje nuevo. El siguiente diagrama muestra la arquitectura detrás de un detector de instantáneas:

Arquitectura de una conexión de escucha de instantáneas

La siguiente secuencia de eventos tiene lugar cuando el Cliente B conecta un detector de instantáneas a la base de datos:

  1. El cliente B abre una conexión a Cloud Firestore y registra un oyente realizando una llamada a onSnapshot(collection("chatroom")) a través del SDK de Firebase. Este oyente puede permanecer activo durante horas.
  2. La interfaz de Cloud Firestore consulta el sistema de almacenamiento subyacente para iniciar el conjunto de datos. Carga todo el conjunto de resultados de documentos coincidentes. Nos referimos a esto como una consulta de sondeo . Luego, el sistema evalúa las reglas de seguridad de Firebase de la base de datos para verificar que el usuario pueda acceder a estos datos. Si el usuario está autorizado, la base de datos devuelve los datos al usuario.
  3. La consulta del cliente B luego pasa al modo de escucha . El oyente se registra con un controlador de suscripción y espera actualizaciones de los datos.
  4. El cliente A ahora envía una operación de escritura para modificar un documento.
  5. La base de datos confirma el cambio del documento en su sistema de almacenamiento.
  6. Transaccionalmente, el sistema envía la misma actualización a un registro de cambios interno. El registro de cambios establece un orden estricto de cambios a medida que ocurren.
  7. El registro de cambios, a su vez, distribuye los datos actualizados a un grupo de administradores de suscripciones.
  8. Se ejecuta un comparador de consulta inversa para ver si el documento actualizado coincide con algún oyente de instantáneas registrado actualmente. En este ejemplo, el documento coincide con el detector de instantáneas del Cliente B. Como su nombre lo indica, puede considerar el comparador de consultas inversas como una consulta de base de datos normal, pero realizada a la inversa. En lugar de buscar documentos para encontrar aquellos que coincidan con una consulta, busca de manera eficiente entre consultas para encontrar aquellos que coincidan con un documento entrante. Al encontrar una coincidencia, el sistema envía el documento en cuestión a los oyentes de instantáneas. Luego, el sistema evalúa las reglas de seguridad de Firebase de la base de datos para garantizar que solo los usuarios autorizados reciban los datos.
  9. El sistema reenvía la actualización del documento al SDK en el dispositivo del cliente B y se activa la devolución de llamada onSnapshot . Si la persistencia local está habilitada, el SDK también aplica la actualización al caché local.

Una parte clave de la escalabilidad de Cloud Firestore depende de la distribución del registro de cambios a los controladores de suscripción y los servidores frontend. La distribución permite que un único cambio de datos se propague de manera eficiente para atender millones de consultas en tiempo real y usuarios conectados. Al ejecutar muchas réplicas de todos estos componentes en múltiples zonas (o múltiples regiones en el caso de una implementación multirregional), Cloud Firestore logra alta disponibilidad y escalabilidad.

Vale la pena señalar que todas las operaciones de lectura emitidas desde SDK web y móvil siguen el modelo anterior. Realizan una consulta de sondeo seguida del modo de escucha para mantener garantías de coherencia. Esto también se aplica a escuchas en tiempo real, llamadas para recuperar un documento y consultas únicas . Puede pensar en las recuperaciones de documentos únicos y las consultas de una sola vez como escuchas de instantáneas de corta duración que vienen con restricciones similares en cuanto al rendimiento.

Aplicar las mejores prácticas para escalar consultas en tiempo real

Aplique las siguientes mejores prácticas para diseñar consultas escalables en tiempo real.

Comprender el alto tráfico de escritura en el sistema

Esta sección le ayuda a comprender cómo responde el sistema a un número cada vez mayor de solicitudes de escritura.

Los registros de cambios de Cloud Firestore que impulsan las consultas en tiempo real escalan automáticamente horizontalmente a medida que aumenta el tráfico de escritura. A medida que la velocidad de escritura de una base de datos aumenta más allá de lo que un único servidor puede manejar, el registro de cambios se divide entre varios servidores y el procesamiento de consultas comienza a consumir datos de varios controladores de suscripción en lugar de uno. Desde la perspectiva del cliente y del SDK, todo esto es transparente y no se requiere ninguna acción por parte de la aplicación cuando se producen divisiones. El siguiente diagrama demuestra cómo escalan las consultas en tiempo real:

Arquitectura de distribución del registro de cambios

El escalado automático le permite aumentar su tráfico de escritura sin límites, pero a medida que el tráfico aumenta, el sistema puede tardar algún tiempo en responder. Siga las recomendaciones de la regla 5-5-5 para evitar crear un punto de acceso de escritura. Key Visualizer es una herramienta útil para analizar puntos de acceso de escritura.

Muchas aplicaciones tienen un crecimiento orgánico predecible, que Cloud Firestore puede acomodar sin precauciones. Sin embargo, las cargas de trabajo por lotes, como la importación de un gran conjunto de datos, pueden aumentar las escrituras demasiado rápido. Al diseñar su aplicación, tenga en cuenta de dónde proviene su tráfico de escritura.

Comprender cómo interactúan las escrituras y las lecturas.

Puede pensar en el sistema de consulta en tiempo real como una tubería que conecta las operaciones de escritura con los lectores. Cada vez que se crea, actualiza o elimina un documento, el cambio se propaga desde el sistema de almacenamiento a los oyentes registrados actualmente. La estructura del registro de cambios de Cloud Firestore garantiza una sólida coherencia, lo que significa que su aplicación nunca recibe notificaciones de actualizaciones que estén fuera de orden en comparación con el momento en que la base de datos confirmó los cambios de datos. Esto simplifica el desarrollo de aplicaciones al eliminar los casos extremos relacionados con la coherencia de los datos.

Esta canalización conectada significa que una operación de escritura que cause puntos de acceso o contención de bloqueos puede afectar negativamente las operaciones de lectura. Cuando las operaciones de escritura fallan o experimentan limitaciones, una lectura puede detenerse esperando datos consistentes del registro de cambios. Si esto sucede en su aplicación, es posible que vea operaciones de escritura lentas y tiempos de respuesta lentos correlacionados para las consultas. Evitar los puntos críticos es la clave para evitar este problema.

Mantenga los documentos y las operaciones de escritura pequeños

Al crear aplicaciones con detectores de instantáneas, normalmente desea que los usuarios se enteren rápidamente de los cambios en los datos. Para lograr esto, trate de mantener las cosas pequeñas. El sistema puede enviar documentos pequeños con decenas de campos a través del sistema muy rápidamente. Los documentos más grandes con cientos de campos y una gran cantidad de datos tardan más en procesarse.

Del mismo modo, favorezca operaciones de escritura y confirmación breves y rápidas para mantener baja la latencia. Los lotes grandes pueden brindarle un mayor rendimiento desde la perspectiva del escritor, pero en realidad pueden aumentar el tiempo de notificación para los oyentes de instantáneas. Esto suele resultar contradictorio en comparación con el uso de otros sistemas de bases de datos en los que se podría utilizar el procesamiento por lotes para mejorar el rendimiento.

Utilice oyentes eficientes

A medida que aumentan las velocidades de escritura de su base de datos, Cloud Firestore divide el procesamiento de datos entre muchos servidores. El algoritmo de fragmentación de Cloud Firestore intenta ubicar datos de la misma colección o grupo de colecciones en el mismo servidor de registro de cambios. El sistema intenta maximizar el rendimiento de escritura posible manteniendo al mismo tiempo el número de servidores involucrados en el procesamiento de una consulta lo más bajo posible.

Sin embargo, ciertos patrones aún podrían generar un comportamiento subóptimo para los oyentes de instantáneas. Por ejemplo, si su aplicación almacena la mayoría de sus datos en una colección grande, es posible que el oyente necesite conectarse a muchos servidores para recibir todos los datos que necesita. Esto sigue siendo cierto incluso si aplica un filtro de consulta. Conectarse a muchos servidores aumenta el riesgo de respuestas más lentas.

Para evitar estas respuestas más lentas, diseñe su esquema y aplicación de modo que el sistema pueda atender a los oyentes sin tener que acudir a muchos servidores diferentes. Quizás funcione mejor dividir los datos en colecciones más pequeñas con velocidades de escritura más pequeñas.

Esto es similar a pensar en las consultas de rendimiento en una base de datos relacional que requieren escaneos completos de la tabla. En una base de datos relacional, una consulta que requiere un escaneo completo de la tabla es el equivalente a un detector de instantáneas que observa una colección con alta rotación. Es posible que funcione lentamente en comparación con una consulta que la base de datos puede atender utilizando un índice más específico. Una consulta con un índice más específico es como un detector de instantáneas que observa un único documento o una colección que cambia con menos frecuencia. Debe realizar una prueba de carga de su aplicación para comprender mejor el comportamiento y la necesidad de su caso de uso.

Mantenga las consultas de sondeo rápidas

Otra parte clave de las consultas receptivas en tiempo real implica asegurarse de que la consulta de sondeo para iniciar los datos sea rápida y eficiente. La primera vez que se conecta un nuevo oyente de instantáneas, el oyente debe cargar el conjunto de resultados completo y enviarlo al dispositivo del usuario. Las consultas lentas hacen que su aplicación responda menos. Esto incluye, por ejemplo, consultas que intentan leer muchos documentos o consultas que no utilizan los índices adecuados.

En algunas circunstancias, un oyente también podría volver de un estado de escucha a un estado de votación. Esto sucede automáticamente y es transparente para los SDK y su aplicación. Las siguientes condiciones pueden desencadenar un estado de sondeo:

  • El sistema reequilibra un registro de cambios debido a cambios en la carga.
  • Los puntos de acceso provocan escrituras fallidas o retrasadas en la base de datos.
  • Los reinicios transitorios del servidor afectan temporalmente a los oyentes.

Si sus consultas de sondeo son lo suficientemente rápidas, el estado de sondeo se vuelve transparente para los usuarios de su aplicación.

Favorecer a los oyentes longevos

Abrir y mantener activos a los oyentes durante el mayor tiempo posible suele ser la forma más rentable de crear una aplicación que utilice Cloud Firestore. Cuando utiliza Cloud Firestore, se le factura por los documentos devueltos a su aplicación y no por mantener una conexión abierta. Un oyente de instantáneas de larga duración lee solo los datos que necesita para atender la consulta durante toda su vida. Esto incluye una operación de sondeo inicial seguida de notificaciones cuando los datos realmente cambian. Las consultas únicas, por otro lado, vuelven a leer datos que pueden no haber cambiado desde la última vez que la aplicación ejecutó la consulta.

En los casos en que su aplicación deba consumir una gran cantidad de datos, es posible que los oyentes de instantáneas no sean apropiados. Por ejemplo, si su caso de uso envía muchos documentos por segundo a través de una conexión durante un período prolongado, podría ser mejor optar por consultas únicas que se ejecuten con una frecuencia más baja.

Que sigue