Recomendaciones

Puedes utilizar estas recomendaciones como una referencia rápida de lo que debes tener en cuenta al momento de crear una aplicación que utilice Google Cloud Datastore. Si recién empiezas a usar Cloud Datastore, es posible que en esta página no encuentres los conceptos básicos sobre cómo utilizarlo. Si eres un usuario nuevo, te recomendamos la página Cómo comenzar a utilizar la API de Google Cloud Datastore.

General

  • Utiliza siempre caracteres UTF-8 para nombres de espacio de nombres, nombres de categorías, nombres de propiedad y nombres de claves personalizadas. Los caracteres que no son UTF-8 y se utilicen en esos nombres pueden interferir en la funcionalidad de Cloud Datastore. Por ejemplo: Usar un carácter que no es UTF-8 en un nombre de propiedad podría impedir la creación de un índice utilizado por esta propiedad.
  • No uses una barra diagonal / en nombres de categorías o de claves personalizados. Las barras diagonales podrían interferir en funcionalidades futuras si se utilizan en estos nombres.
  • Evita almacenar información sensible en un ID del proyecto de Cloud. El ID del proyecto de Cloud podría conservarse aún después de que finalice tu proyecto.

Llamadas a la API

  • Utiliza operaciones por lotes en lugar de operaciones individuales para tus lecturas, escrituras y eliminaciones. Las operaciones por lotes son más eficientes debido a que realizan operaciones múltiples con la misma sobrecarga que una operación individual.
  • Si una transacción falla, intenta revertir la transacción. La reversión minimiza la latencia de reintento de una solicitud diferente que compite por los mismos recursos en una transacción. Ten en cuenta que la reversión puede fallar, por lo tanto, debe considerarse solo como un último recurso.
  • Utiliza llamadas asíncronas en vez de síncronas cuando sea posible. Las llamadas asíncronas minimizan el impacto de la latencia. Por ejemplo, considera una aplicación que necesite el resultado de un lookup() síncrono y de una consulta antes de procesar una respuesta. Si el lookup() y la consulta no tienen una dependencia de datos no es necesario esperar de manera síncrona hasta que finalice el lookup() para iniciar la consulta.

Entidades

  • Agrupa datos muy relacionados entre sí en grupos de entidad. Los grupos de entidad habilitan consultas principales que muestran resultados con coherencia sólida. Las consultas principales también realizan una búsqueda rápida en grupos de entidad con E/S mínima debido a que las entidades de estos grupos están almacenadas en lugares físicamente cercanos en los servidores de Cloud Datastore.
  • Evita escribir a un grupo de entidad más de una vez por segundo. Escribir en una frecuencia sostenida por encima del límite hace que las lecturas de coherencia eventual aumenten la eventualidad, provoca que se agote el tiempo de espera de las lecturas de coherencia sólida y genera un rendimiento general de tu aplicación más lento. Una escritura por lotes o transaccional en un grupo de entidad cuenta solo como una escritura individual en este límite.
  • No incluyas la misma entidad (por clave) varias veces en la misma confirmación. Incluir la misma entidad varias veces en la misma confirmación puede afectar la latencia de Cloud Datastore.

Claves

  • Los nombres de las claves se generan de forma automática si no se proporcionaron al momento de la creación de la entidad. Se asignan de manera tal de estar distribuidas de forma uniforme en el espacio de claves.
  • Para una clave que use un nombre personalizado, siempre utiliza caracteres UTF-8, excepto la barra diagonal (/). Los caracteres que no son UTF-8 interfieren en varios procesos, como importar una copia de seguridad de Cloud Datastore a Google BigQuery. Una barra diagonal puede interferir en funcionalidades futuras.
  • Para una clave que use un ID numérico:
    • No utilices un número negativo para el ID. Un ID negativo puede interferir en el ordenamiento.
    • No utilices el valor 0(cero) para el ID. Si lo haces, obtendrás un ID asignado de manera automática.
    • Si deseas asignar manualmente tus propios ID numéricos a las entidades que creaste, haz que tu aplicación obtenga un bloque de ID con el método allocateIds(). Eso evitará que Cloud Datastore asigne uno de tus ID numéricos manuales a otra entidad.
  • Si asignas tu propio ID numérico manual o nombre personalizado a las entidades que creaste, no utilices valores monótonamente crecientes como:

    1, 2, 3, …,
    "Customer1", "Customer2", "Customer3", ….
    "Product 1", "Product 2", "Product 3", ….
    

    Si una aplicación genera un tráfico alto, esa numeración secuencial podría dar lugar a hotspots que afectan la latencia de Cloud Datastore. Para evitar el problema de los ID numéricos secuenciales, obtén ID numéricos con el método allocateIds(). El método allocateIds() genera secuencias de ID numéricos bien distribuidas.

  • Al momento de especificar una clave o almacenar el nombre generado, puedes realizar una lookup() coherente en esa entidad más tarde sin la necesidad de realizar una consulta para encontrar la entidad.

Índices

Propiedades

  • Utiliza siempre caracteres UTF-8 para propiedades de tipo string. Un carácter que no sea UTF-8 en una propiedad de tipo string podría interferir en las consultas. Si necesitas guardar datos que contengan caracteres que no son UTF-8, utiliza un byte string.
  • No utilices puntos en los nombres de las propiedades. Los puntos utilizados en los nombres de las propiedades pueden interferir en indexaciones futuras de propiedades estructuradas.

Consultas

  • Si necesitas acceder solo a la clave desde los resultados de la consulta, utiliza una consulta de solo claves. Una consulta de solo claves muestra los resultados a una latencia y costo más bajos que cuando se recuperan las entidades completas.
  • Si solo necesitas acceder a propiedades específicas de una entidad, utiliza una consulta de proyección. Una consulta de proyección muestra los resultados a una latencia y costo más bajos que cuando se recuperan las entidades completas.
  • Del mismo modo, si solo necesitas acceder a las propiedades que están incluidas en el filtro de consulta (por ejemplo, aquellas que se muestran en una cláusula order by), utiliza una consulta de proyección.
  • No uses compensaciones. En su lugar, utiliza cursores. Utilizar una compensación solo evita que las entidades omitidas se recuperen en tu aplicación, pero igual se recuperan de forma interna. Las entidades omitidas afectan la latencia de la consulta y tu aplicación se factura de acuerdo con las operaciones de lectura requeridas para recuperarlas.
  • Si necesitas una coherencia sólida para tus consultas, utiliza una consulta principal (si quieres usar consultas principales, primero necesitas estructurar tus datos para lograr la coherencia sólida). Una consulta principal muestra resultados con coherencia sólida. Ten en cuenta que una consulta no principal de solo claves seguida de un lookup() no muestra resultados sólidos, ya que una consulta no principal de solo claves podría obtener resultados de un índice que no es coherente al momento de la consulta.

Cómo diseñar para la escala

Actualizaciones para un grupo de entidad único

Un grupo de entidad único en Cloud Datastore no debe actualizarse con demasiada rapidez.

Si estás utilizando Cloud Datastore, Google recomienda que diseñes tu aplicación de manera tal que no necesite actualizar un grupo de entidad más de una vez por segundo. Recuerda que una entidad sin entidad superior ni secundaria es su propio grupo de entidad. Si actualizas un grupo de entidad con demasiada rapidez, tus operaciones de escritura de Cloud Datastore tendrán tiempos de espera y latencia mayores y otros tipos de errores. Esto se conoce como contención.

A veces, las tasas de escritura de Cloud Datastore para un grupo de entidad pueden exceder el límite de una por segundo, por lo que las pruebas de carga podrían no mostrar este problema. Puedes encontrar algunas sugerencias para diseñar tu aplicación a fines de reducir las tasas de operaciones de escritura en grupos de entidad en el artículo de contención de Cloud Datastore.

Tasas altas de lectura/escritura para un rango pequeño de claves

Evita las tasas altas de lectura o escritura en claves de Cloud Datastore que se encuentren cerca lexicográficamente.

Cloud Datastore está compilado sobre la base de datos NoSQL de Google NoSQL, Bigtable, y está sujeto a sus características de rendimiento. Bigtable realiza el escalamiento mediante la fragmentación de filas en tablets separadas y estas filas se ordenan de manera lexicográfica por clave.

Si estás utilizando Cloud Datastore, puedes obtener lecturas lentas debido a una sobrecarga de la tablet si hay aumento repentino en la tasa de escritura a un rango pequeño de claves que excede la capacidad de un servidor de tablet único. En algún momento, Bigtable dividirá la tabla para que soporte cargas altas.

El límite de operaciones de lectura suele ser más alto que el de las de escritura, a menos que la lectura sea desde una clave única a una tasa alta. Bigtable no puede separar una clave única en más de una tablet.

Las tablets sobrecargadas se pueden aplicar a los rangos de clave utilizados por las claves de entidad y por los índices.

En algunos casos, un hotspot de Cloud Datastore puede causar un impacto mayor en una aplicación que prevenir operaciones de lectura o escritura en un rango pequeño de claves. Por ejemplo, las teclas de acceso rápido se pueden leer o escribir durante el inicio de la instancia y eso causaría que la carga de solicitudes falle.

De forma predeterminada, Cloud Datastore asigna claves con un algoritmo de dispersión. Por lo tanto, en general, no encontrarás generación de hotspots en operaciones de escritura de Cloud Datastore si creas nuevas entidades con una tasa de escritura alta con la política de asignación de ID predeterminada. Existen algunos casos excepcionales donde puedes encontrar este problema:

  • Si creas entidades nuevas a una tasa muy alta con la política de asignación de ID secuencial heredada.

  • Si creas entidades nuevas a una tasa muy alta y te asignas tus propios ID que aumentan monótonamente.

  • Si creas entidades nuevas a una tasa muy alta para categorías que antes tenían muy pocas entidades existentes. Bigtable comenzará con todas las entidades en un mismo servidor de tablet y le llevará un tiempo dividir el rango de claves en servidores de tablet separados.

  • También verás este problema si creas entidades nuevas a una tasa alta con una propiedad indexada que aumenta monótonamente, como una marca de tiempo, debido a que estas propiedades son las claves para las filas de las tablas de índice en Bigtable.

  • Cloud Datastore antecede el espacio de nombres y el tipo de grupo de entidad raíz a la fila de claves de Bigtable. Puedes encontrar un hotspot si comienzas a escribir en un nuevo espacio de nombres o categorías sin aumentar el tráfico de manera gradual.

Si tienes una clave o una propiedad indexada que aumentará monótonamente, entonces puedes agregar un hash al azar para asegurarte de que las claves se compartan a múltiples tablets.

De la misma manera, si necesitas consultar una propiedad que aumenta (o disminuye) monótonamente con un orden o un filtro, podrías indexar una nueva propiedad, para la cual debes prefijar el valor monótono con un valor que tenga cardinalidad alta a lo largo del conjunto de datos, pero que es común a todas las entidades en el alcance de la consulta que quieres realizar. Por ejemplo, si quieres consultar entradas por marcas de tiempo, pero solo necesitas que muestre resultados para un usuario por vez, puedes prefijar la marca de tiempo con el id del usuario y luego indexar esa nueva propiedad. Esto permitirá consultas y ofrecerá los resultados en orden para ese usuario, pero la presencia del id del usuario garantizará que el índice esté bien fragmentado.

Para una explicación más detallada de este problema, consulta el blog de Ikai Lan sobre cómo guardar valores que aumentan monótonamente en Cloud Datastore.

Cómo acelerar el tráfico

Acelerar el tráfico de manera gradual en nuevas categorías o partes del espacio de claves en Cloud Datastore.

Debes acelerar gradualmente el tráfico en categorías nuevas de Cloud Datastore a fin de que Bigtable tenga el tiempo suficiente para dividir las tablets a medida que aumenta el tráfico. Recomendamos realizar un máximo de 500 operaciones por segundo en una categoría nueva de Cloud Datastore y luego aumentar el tráfico en un 50% cada 5 minutos. En teoría, puedes alcanzar 740,000 operaciones por segundo después de utilizar este programa de aceleración por 90 minutos. Asegúrate de que las operaciones de escritura se encuentren distribuidas de manera uniforme en todo el rango de claves. Nuestros SRE lo llaman la regla "500/50/5".

Este patrón de aceleración gradual es muy importante si cambias tu código para dejar de utilizar la categoría A y comienzas a utilizar la categoría B. Una manera simple de realizar esta migración es cambiar tu código para que lea la categoría B y, si no existe, lea la categoría A. Sin embargo, esto puede causar un incremento repentino en el tráfico en una nueva categoría con una porción muy pequeña del espacio de claves. Puede que Bigtable no sea capaz de dividir de manera eficiente las tablets si el espacio de claves está disperso.

El mismo problema puede surgir si migras tus entidades para utilizar un rango de claves diferente dentro de la misma categoría.

La estrategia que utilices para migrar entidades a una nueva categoría o clave dependerá de tu nuevo modelo de datos. A continuación, puedes encontrar una estrategia de ejemplo conocida como "Lecturas paralelas". Tendrás que determinar si esta estrategia es eficaz para tus datos o no. Un punto importante a tener en cuenta será el impacto del costo de las operaciones paralelas durante la migración.

Lee primero la entidad o la clave antigua. Si esa falta, entonces puedes leer desde la entidad o clave nueva. Una tasa alta de lecturas de entidades no existentes puede causar una generación de hotspots, por lo tanto, debes asegurarte de incrementar la carga de manera gradual. Una mejor estrategia es copiar la entidad antigua a la nueva y luego borrar la antigua. Acelera las lecturas paralelas de manera gradual para asegurarte de que el nuevo espacio de claves esté divido correctamente.

Una estrategia posible para acelerar lecturas o escrituras de manera gradual en una categoría nueva es utilizar un hash determinista del ID del usuario para obtener un porcentaje aleatorio de usuarios que escriban nuevas entidades. Asegúrate de que el resultado del hash del ID de usuario no se encuentre sesgado ni por tu función aleatoria ni por el comportamiento de tu usuario.

Mientras tanto, ejecuta un trabajo de Dataflow para copiar todos tus datos de las entidades o claves antiguas a las nuevas. Tu trabajo en lotes debe evitar escrituras de claves secuenciales para impedir hotspots de Bigtable. Cuando tu trabajo en lotes está completo, solo puedes leer desde la nueva ubicación.

Una mejor manera de realizar esta estrategia es migrar lotes pequeños de usuarios al mismo tiempo. Agrega un campo a la entidad de usuario que rastrea el estado de la migración de ese usuario. Selecciona un lote de usuarios que deseas migrar basado en un hash del ID de usuario. Un trabajo de Mapreduce o Dataflow migrará las claves de esos lotes de usuarios. Los usuarios que tengan una migración en curso utilizarán lecturas paralelas.

Ten en cuenta que no es fácil revertir el proceso, a menos que realices operaciones de escritura duales de las entidades antiguas y nuevas durante la fase de migración. Eso incrementará los costos incurridos por Cloud Datastore.

Eliminaciones

Evita borrar una gran cantidad de entidades de Cloud Datastore en un rango pequeño de claves.

Bigtable reescribe de manera periódica sus tablas para quitar entidades borradas y reorganizar tus datos a fines de que las operaciones de lectura y escritura sean más eficientes. Este proceso se conoce como una compactación.

Si borras una gran cantidad de entidades en un rango pequeño de claves, las consultas de esa parte del índice serán más lentas hasta que la compactación se haya completado. En casos extremos, tus consultas pueden agotar el tiempo de espera antes de mostrar resultados.

Es un antipatrón utilizar un valor de marca de tiempo de un campo indexado para representar el tiempo de caducidad de una entidad. Para recuperar entidades vencidas, necesitarás consultar campos indexados que probablemente se encuentren en una parte superpuesta del espacio de claves con entradas de índice para las entidades borradas más recientes.

Puedes mejorar el rendimiento con "consultas de fragmentación" que agregan una string de longitud fija a la marca de tiempo de vencimiento. El índice está ordenado en la string completa para que las entidades con las mismas marcas de tiempo se puedan localizar a lo largo del rango de claves del índice. Puedes ejecutar múltiples consultas en paralelo para recuperar resultados de cada fragmentación.

Una solución más completa para el problema de la marca de tiempo de vencimiento es un "número de generación", un contador global que se actualiza de manera periódica. El número de generación está agregado en la marca de tiempo de vencimiento para que las consultas se ordenen por número de generación, luego por fragmentación y luego por marca de tiempo. La eliminación de las entidades antiguas ocurre en una generación anterior. El número de generación de una entidad que no se borró debería aumentar. Una vez que la eliminación está completa, avanzas a la próxima generación. Las consultas por una generación antigua no se realizarán correctamente hasta que la compactación esté completa. Podrías tener que esperar que varias generaciones se completen para poder consultar el índice y obtener la lista de entidades que borrar a fin de reducir el riesgo de que falten resultados debido a una coherencia eventual.

Fragmentación y replicación

Utiliza fragmentación o replicación para las claves de Cloud Datastore sobrecargadas.

Puedes utilizar la replicación si necesitas leer una parte del rango de la clave a una tasa más alta que la permitida por Bigtable. Si utilizas esta estrategia, almacenarás N copias de la misma entidad, lo cual permite una tasa de lectura N veces más alta que la admitida por una entidad única.

Puedes utilizar la fragmentación si necesitas escribir una parte del rango de la clave a una tasa más alta que la permitida por Bigtable. La fragmentación divide una entidad en unidades más pequeñas. Los principios se explican en el artículo fragmentación de contadores.

Algunos de los errores más comunes de fragmentación son:

  • Fragmentar con un prefijo de tiempo. Luego de que el tiempo se desplaza al siguiente prefijo, la parte nueva sin dividir se convierte en un hotspot. En cambio, debes desplazar de manera gradual una parte de tu escritura al nuevo prefijo.

  • Fragmentar solo las entidades más sobrecargadas. Si fragmentas una pequeña proporción del número total de entidades, podría no haber filas suficientes entre las entidades sobrecargadas para asegurar de que permanezcan en divisiones diferentes.

¿Qué sigue?

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Documentación de Cloud Datastore