sql >> Base de Datos >  >> RDS >> Mysql

Una guía para comprender los patrones de escalado de bases de datos

Hay muchos artículos en línea que describen los patrones de escalabilidad de la base de datos, pero en su mayoría son artículos dispersos, solo técnicas que se definen al azar sin mucho contexto. Encuentro que no están definidos paso a paso, y no discuten cuándo elegir qué opción de escala, qué opciones de escala son factibles en la práctica y por qué.

Por lo tanto, planeo discutir algunas de las técnicas en detalle en futuros artículos. Para empezar, siento que es mejor si discuto las técnicas paso a paso con algo de contexto a mi manera. Este artículo es un artículo de alto nivel:no discutiré las técnicas de escalado en detalle aquí, pero proporcionaré una descripción general. Así que empecemos.

Un estudio de caso

Suponga que ha creado una startup que ofrece viajes compartidos a un costo económico. Inicialmente, cuando comienza, se dirige a una ciudad y apenas tiene decenas de clientes después de su anuncio inicial.

Guarda todos los clientes, viajes, ubicaciones, datos de reservas e historial de viajes de clientes en la misma base de datos o, muy probablemente, en una sola máquina física. No hay un almacenamiento en caché sofisticado o una gran canalización de datos para resolver problemas, ya que su aplicación es muy nueva. Esto es perfecto para su caso de uso en este momento ya que hay muy pocos clientes y su sistema apenas reserva 1 viaje en 5 minutos, por ejemplo.

Pero a medida que pasa el tiempo, más personas comienzan a registrarse en su sistema ya que es el servicio más barato del mercado y gracias a su promoción y anuncios. Comienzas a reservar, digamos, 10 reservas por minuto, y lentamente el número aumenta a 20, 30 reservas por minuto.

En este momento, se da cuenta de que el sistema ha comenzado a funcionar de manera deficiente:la latencia de la API ha aumentado mucho y algunas transacciones se bloquean o mueren de hambre y, finalmente, fallan. Su aplicación está tardando más en responder, lo que provoca la insatisfacción de los clientes. ¿Qué puedes hacer para resolver el problema?

Patrón 1:optimización de consultas e implementación del grupo de conexiones:

La primera solución que viene a la mente es que el caché utiliza con frecuencia datos no dinámicos como el historial de reservas, el historial de pagos, los perfiles de usuario, etc. Pero después de este almacenamiento en caché de la capa de aplicación, no puede resolver el problema de latencia de las API que exponen datos dinámicos como la ubicación actual del conductor o los taxis más cercanos para un cliente determinado o el costo actual del viaje en un momento determinado después de que comienza el viaje.

Identifica que su base de datos probablemente esté muy normalizada, por lo que introduce algunas columnas redundantes (estas columnas aparecen con frecuencia en WHERE o JOIN ON cláusula en consultas) en tablas muy utilizadas en aras de la desnormalización. Esto reduce las consultas conjuntas, divide una consulta grande en múltiples consultas más pequeñas y agrega sus resultados en la capa de aplicación.

Otra optimización paralela que puede hacer es modificar las conexiones de la base de datos. Las bibliotecas de clientes de bases de datos y las bibliotecas externas están disponibles en casi todos los lenguajes de programación. Puede usar bibliotecas de grupos de conexiones para almacenar en caché las conexiones de la base de datos o puede configurar el tamaño del grupo de conexiones en el propio sistema de administración de la base de datos.

La creación de cualquier conexión de red es costosa, ya que requiere cierta comunicación de ida y vuelta entre el cliente y el servidor. La agrupación de conexiones puede ayudarlo a optimizar la cantidad de conexiones. Las bibliotecas de grupos de conexiones pueden ayudarlo a multiplexar conexiones:múltiples subprocesos de aplicaciones pueden usar la misma conexión de base de datos. Veré si puedo explicar la agrupación de conexiones en detalle en un artículo separado más adelante.

Mida la latencia de sus API y encuentre probablemente una latencia reducida del 20% al 50% o más. Esta es una buena optimización en este momento.

Ahora ha escalado su negocio a una ciudad más, se registran más clientes, lentamente comienza a hacer de 80 a 100 reservas por minuto. Su sistema no es capaz de manejar esta báscula. Una vez más, verá que la latencia de la API ha aumentado, la capa de la base de datos se ha rendido, pero esta vez, ninguna optimización de consultas le brinda una ganancia de rendimiento significativa. Verifica la métrica del sistema, encuentra que el espacio en disco está casi lleno, la CPU está ocupada el 80% del tiempo, la RAM se llena muy rápido.

Patrón 2 - Escalado vertical o escalado:

Después de examinar todas las métricas del sistema, sabe que no hay otra solución fácil que actualizar el hardware del sistema. Actualizas el tamaño de tu RAM 2 veces, actualizas el espacio en disco, digamos, 3 veces o más. Esto se denomina escalado vertical o escalado vertical de su sistema. Informa a su equipo de infraestructura o equipo de desarrollo o agentes del centro de datos de terceros para actualizar su máquina.

Pero, ¿cómo se configura la máquina para el escalado vertical?

Asignas una máquina más grande. Un enfoque es no migrar datos manualmente desde la máquina anterior, sino configurar la nueva máquina como replica a la máquina existente (primary )-crear una primary replica temporal configuración. Deje que la replicación suceda naturalmente. Una vez finalizada la replicación, promueva la nueva máquina a principal y desconecte la máquina anterior. Dado que se espera que la máquina más grande atienda todas las solicitudes, todas las lecturas y escrituras se realizarán en esta máquina.

Frio. Su sistema vuelve a funcionar con un mayor rendimiento.

Su negocio va muy bien y decide escalar a 3 ciudades más; ahora está operativo en 5 ciudades en total. El tráfico es 3 veces mayor que antes, se espera que haga alrededor de 300 reservas por minuto. Incluso antes de lograr este objetivo de reserva, vuelve a tener problemas de rendimiento, el tamaño del índice de la base de datos está aumentando considerablemente en la memoria, necesita un mantenimiento constante, el escaneo de tablas con el índice se está volviendo más lento que nunca. Calcula el costo de ampliar aún más la máquina, pero no está convencido del costo. ¿Qué haces ahora?

Patrón 3 - Segregación de responsabilidad de consulta de comandos (CQRS):

Identifica que la máquina grande no puede manejar todas las read/write peticiones. Además, en la mayoría de los casos, cualquier empresa necesita capacidad transaccional en write pero no en read operaciones. También está bien con un poco de read inconsistente o retrasada operaciones y su negocio tampoco tiene problemas con eso. Ve una oportunidad en la que podría ser una buena opción separar el read &write operaciones físicas en cuanto a máquina. Creará un margen para que las máquinas individuales manejen más read/write operaciones.

Ahora toma dos máquinas grandes más y las configura como replica a la máquina actual. La replicación de la base de datos se encargará de distribuir los datos desde primary máquina a replica máquinas. Navegas por todas las consultas de lectura (Consulta (Q ) en CQRS ) a las réplicas:cualquier replica puede atender cualquier solicitud de lectura, navega por todas las consultas de escritura (Comando (C ) en CQRS ) al primary . Puede haber un pequeño retraso en la replicación, pero de acuerdo con el caso de uso de su negocio, está bien.

La mayoría de las empresas emergentes de mediana escala que atienden cientos de miles de solicitudes todos los días pueden sobrevivir con una configuración de réplica principal siempre que archiven periódicamente los datos más antiguos.

Ahora escalas a 2 ciudades más, ves que tu primary no es capaz de manejar todos los write peticiones. Muchos write las solicitudes tienen latencia. Además, el retraso entre primary &replica a veces afecta a los clientes y conductores, por ejemplo:cuando finaliza el viaje, el cliente paga al conductor con éxito, pero el conductor no puede ver el pago ya que la actividad del cliente es una write solicitud que va al primary , mientras que la actividad del conductor es una read petición que va a una de las réplicas. Su sistema en general es tan lento que el conductor no puede ver el pago durante al menos medio minuto, lo que es frustrante tanto para el conductor como para el cliente. ¿Cómo lo resuelves?

Patrón 4:replicación primaria múltiple

Escalaste muy bien con primary-replica configuración, pero ahora necesita más rendimiento de escritura. Es posible que esté listo para comprometerse un poco en read solicitud de rendimiento. ¿Por qué no distribuir la solicitud de escritura a una replica? también?

En un multi-primary configuración, todas las máquinas pueden funcionar tanto como primary &replica . Puedes pensar en multi-primary como un círculo de máquinas decir A->B->C->D->A . B puede replicar datos de A , C puede replicar datos de B , D puede replicar datos de C , A puede replicar datos de D . Puede escribir datos en cualquier nodo, mientras lee datos, puede transmitir la consulta a todos los nodos, cualquiera que responda lo devuelve. Todos los nodos tendrán el mismo esquema de base de datos, el mismo conjunto de tablas, índice, etc. Por lo tanto, debe asegurarse de que no haya colisiones en id a través de los nodos en la misma tabla; de lo contrario, durante la transmisión, varios nodos devolverían datos diferentes para el mismo id .

Generalmente es mejor usar UUID o GUID para identificación Una desventaja más de esta técnica es:read las consultas pueden ser ineficientes, ya que implica transmitir la consulta y obtener el resultado correcto, básicamente un enfoque de recopilación dispersa.

Ahora escalas a 5 ciudades más y tu sistema vuelve a sufrir. Se espera que maneje aproximadamente 50 solicitudes por segundo. Tiene una necesidad desesperada de manejar una gran cantidad de solicitudes simultáneas. ¿Cómo logras eso?

Patrón 5 - Partición:

Sabes que tu location la base de datos es algo que se está volviendo alto write &read tráfico. Probablemente write:read la proporción es 7:3 . Esto está ejerciendo mucha presión sobre las bases de datos existentes. La location las tablas contienen pocos datos primarios como longitude , latitude , timestamp , driver id , trip id etc. No tiene mucho que ver con los viajes de los usuarios, los datos de los usuarios, los datos de pago, etc. ¿Qué hay de separar la location? tablas en un esquema de base de datos separado? ¿Qué hay de poner esa base de datos en máquinas separadas con la primary-replica adecuada? o multi-primary ¿configuración?

Esto se denomina partición de datos por funcionalidad. Diferentes bases de datos pueden alojar datos categorizados por diferentes funcionalidades, si es necesario, el resultado se puede agregar en la capa de back-end. Con esta técnica, puede concentrarse en escalar bien aquellas funcionalidades que exigen un alto nivel de read/write peticiones. Aunque el back-end o la capa de la aplicación tiene que asumir la responsabilidad de unir los resultados cuando sea necesario, lo que probablemente genere más cambios en el código.

Ahora imagine que ha expandido su negocio a un total de 20 ciudades en su país y planea expandirse a Australia pronto. Su creciente demanda de aplicaciones requiere una respuesta cada vez más rápida. Ninguno de los métodos anteriores puede ayudarte al extremo ahora. Debe escalar su sistema de tal manera que la expansión a otros países/regiones no siempre requiera cambios frecuentes de ingeniería o arquitectura. ¿Cómo haces eso?

Patrón 6 - Escalado horizontal:

Busca mucho en Google, lee mucho sobre cómo otras empresas han resuelto el problema y llega a la conclusión de que necesita escalar horizontalmente. Asigna, digamos, 50 máquinas:todas tienen el mismo esquema de base de datos que, a su vez, contiene el mismo conjunto de tablas. Todas las máquinas sólo tienen una parte de los datos.

Dado que todas las bases de datos contienen el mismo conjunto de tablas, puede diseñar el sistema de tal manera que la localidad de los datos esté allí, es decir; todos los datos relacionados aterrizan en la misma máquina. Cada máquina puede tener sus propias réplicas, las réplicas se pueden usar en la recuperación de fallas. Cada una de las bases de datos se llama shard . Una máquina física puede tener uno o varios shards — Depende de su diseño cómo lo desee. Debe decidir sobre sharding key de tal manera que una sola sharding key siempre se refiere a la misma máquina. Entonces, puede imaginar muchas máquinas que contienen datos relacionados en el mismo conjunto de tablas, read/write las solicitudes para la misma fila o el mismo conjunto de recursos aterrizan en la misma máquina de base de datos.

La fragmentación es en general difícil, al menos los ingenieros de diferentes compañías dicen eso. Pero cuando atiendes millones o miles de millones de solicitudes, tienes que tomar una decisión tan difícil.

Hablaré sobre sharding con mayor detalle en mi próxima publicación, por lo que reprimí mi tentación de discutir más en esta publicación.

Ahora que ha implementado la fragmentación, está seguro de que puede escalar a muchos países. Su negocio ha crecido tanto que los inversionistas lo presionan para escalar el negocio en todos los continentes. Vuelve a ver algún problema aquí. Latencia de la API de nuevo. Su servicio está alojado en EE. UU. y la gente de Vietnam está teniendo dificultades para reservar viajes. ¿Por qué? ¿Qué haces al respecto?

Patrón 7 - Partición inteligente del centro de datos:

Su negocio está creciendo en América, el sur de Asia y en algunos países de Europa. Estás haciendo millones de reservas diariamente con miles de millones de solicitudes llegando a tu servidor. Felicidades, este es un momento cumbre para su negocio.

Pero como las solicitudes de la aplicación tienen que viajar a través de los continentes a través de cientos o miles de servidores en Internet, surge la latencia. ¿Qué pasa con la distribución del tráfico entre los centros de datos? Puede configurar un centro de datos en Singapur que maneje todas las solicitudes del sur de Asia, un centro de datos en Alemania puede manejar todas las solicitudes de países europeos y un centro de datos de California puede manejar todas las solicitudes de EE. UU.

También habilita la replicación entre centros de datos, lo que ayuda a la recuperación ante desastres. Por lo tanto, si el centro de datos de California realiza la replicación en el centro de datos de Singapur, en caso de que el centro de datos de California se bloquee debido a problemas de electricidad o calamidades naturales, todas las solicitudes de EE. UU. pueden volver al centro de datos de Singapur y así sucesivamente.

Esta técnica de escalado es útil cuando tiene millones de clientes para atender en todos los países y no puede adaptarse a ninguna pérdida de datos, debe mantener siempre la disponibilidad del sistema.

Estas son algunas técnicas generales paso a paso para el escalado de bases de datos. Aunque la mayoría de los ingenieros no tienen la oportunidad suficiente de implementar estas técnicas, en general es mejor tener una idea más amplia sobre dicho sistema que en el futuro puede ayudarlo a hacer un mejor diseño de arquitectura y sistema.

En mis próximos artículos, intentaré discutir algunos de los conceptos en detalle. Siéntase libre de dar comentarios apropiados para esta publicación, si corresponde.

El artículo se publicó originalmente en la cuenta mediana del autor:https://medium.com/@kousiknath/understanding-database-scaling-patterns-ac24e5223522