A continuación se muestra un extracto del capítulo 1 de Desempeño de la base de datos a escala (un libro de acceso abierto que está disponible gratis).Sigue las aventuras altamente ficticias de Joan con algunos desafíos de rendimiento de bases de datos demasiado reales.Rirás. llorarás.Te preguntará cómo hemos transformado esta “historia cheesy” en un libro profundamente técnico. Desempeño de la base de datos a escala Atrapada por impresionantes palabras como “cloud híbrido”, “serverless” y “edge first”, Joan se unió rápidamente a una nueva compañía y comenzó a capturar su pila de tecnología. Su primer proyecto comenzó recientemente una transición de su implementación interna de un sistema de bases de datos, que resultó no escalar al mismo ritmo que el número de clientes, a una de las soluciones de gestión de bases de datos estándar de la industria. Su nueva opción fue una nueva base de datos distribuida, que, a diferencia de NoSQL, se esfuerza por mantener el original. garantías conocidas en el mundo SQL. ácido Debido a unas pocas nuevas leyes de protección de datos que tienden a aparecer anualmente hoy en día, el consejo de administración de la compañía decidió que iban a mantener su propio centro de datos, en lugar de utilizar uno de los proveedores de nube populares para almacenar información sensible. En un nivel muy alto, el producto principal de la compañía consistía en sólo dos capas: El frontend, el punto de entrada para los usuarios, que en realidad se ejecuta en sus propios navegadores y se comunica con el resto del sistema para intercambiar y persistir información. El todo-else, comúnmente conocido como “backend”, pero en realidad incluye balanceadores de carga, autenticación, autorización, múltiples capas de caché, bases de datos, copias de seguridad, y así sucesivamente. La primera tarea introductoria de Joan fue implementar un servicio muy simple para recopilar y resumir varias estadísticas de la base de datos, e integrar ese servicio con todo el ecosistema, de modo que recoge datos de la base de datos en tiempo real y permita a los equipos de DevOps inspeccionar las estadísticas en vivo. Para impresionar a la dirección y asegurarles de que contratar a Joan fue su mejor decisión este trimestre, Joan decidió entregar una implementación de prueba de concepto en su primer día!La política inexplicable de la compañía era escribir software en Rust, por lo que tomó el primer controlador para su base de datos de una breve búsqueda en crates.io y se sentó a su hackathon auto-organizado. El día fue realmente suave, con el ecosistema enfocado en la ergonomía de Rust proporcionando una experiencia de desarrollador superior. Pero luego Joan realizó sus primeras pruebas de humo en un sistema real. La incredulidad se convirtió en decepción y impotencia cuando se dio cuenta de que cada tercera solicitud (en promedio) terminó en un error, a pesar de que todo el clúster de bases de datos informó que estaba en un estado saludable y operable. Desafortunadamente, la conductora Joan se apresuró a elegir la base de su trabajo, aunque el código de código abierto por sí solo, era sólo un delgado envoltorio sobre el código C precompilado, heredado, sin que la fuente se encontrara. y hizo una suposición educada de que el En la base de datos utilizada por la empresa, las claves se hashan a solicitudes de ruta posteriores a nodos apropiados.Si un valor de hash se calcula incorrectamente, una solicitud puede ser reenviada al nodo equivocado que puede rechazarla y devolver un error en su lugar. Wireshark El bug debe estar en la implementación de la clave de hash No pudo verificar la afirmación debido a la falta de código fuente, Joan decidió por un camino más sencillo: abandonar el controlador elegido originalmente y reimplantar la solución en uno de los controladores oficialmente respaldados, de código abierto respaldado por el proveedor de la base de datos, con una base de usuarios sólida y un calendario de lanzamiento actualizado regularmente. Diario de las lecciones aprendidas de Joan, parte I Las lecciones iniciales incluyen: Elige un controlador cuidadosamente.Es el núcleo del rendimiento, la robustez y la fiabilidad de tu código. Los conductores también tienen errores, y es imposible evitarlos. A menos que haya una buena razón, prefiere el conductor oficialmente respaldado (si existe); Los controladores de código abierto tienen ventajas: no solo son verificados por la comunidad, sino que también permiten la inspección profunda de su código, e incluso la modificación del código del controlador para obtener aún más insights para el desgaste. Es mejor confiar en los controladores con un calendario de lanzamiento bien establecido ya que son más propensos a recibir correcciones de errores (incluidas las vulnerabilidades de seguridad) en un período de tiempo razonable. Wireshark es una gran herramienta de código abierto para interpretar paquetes de red; déjalo un intento si desea mirar debajo del capó de su programa. La tarea introductoria fue finalmente completada con éxito, lo que preparó a Joan para recibir su primera tarea real. El tuning Armada con la experiencia adquirida trabajando en la tarea introductoria, Joan comenzó a planear cómo abordar su nueva tarea: una aplicación mal comportada.Una de las aplicaciones causó notoriamente problemas de estabilidad para todo el sistema, perturbando otras cargas de trabajo cada vez que experimentaba cualquier problema. Este servicio en particular fue responsable de inyectar los datos de copia de seguridad del sistema legado en la nueva base de datos. Debido a que la compañía no estaba en gran prisa, la aplicación fue escrita con baja concurrencia en mente para tener baja prioridad y no interferir con las cargas de trabajo de los usuarios. Desafortunadamente, una vez cada unos días algo continuó desencadenando una anomalía. La aplicación normalmente pacífica parecía estar tratando de realizar un ataque de denegación de servicio en su propia base de datos, inundándola con solicitudes hasta que el backend se sobrecargó lo suficiente para causar problemas para otras partes del ecosistema. Mientras Joan observaba las métricas presentadas en un dashboard de Grafana, sugiriendo claramente que la tasa de solicitudes generadas por esta aplicación comenzó a aumentar alrededor del momento de la anomalía, se preguntó cómo en la Tierra esta carga de trabajo podría comportarse de esa manera. Dado que la colaboración fue fuertemente anunciada como una de las "fuentes espirituales y culturales" de la compañía durante las sesiones de embarque con un entrenador en el lugar, decidió que era mejor discutir el asunto con su colega, Tony. “Mira, Tony, no puedo envolver mi cabeza en torno a esto”, explicó. “Este servicio no envía ninguna nueva solicitud cuando 100 de ellas ya están en vuelo. Y mira bien aquí en los registros: 100 solicitudes en curso, uno devolvió un error de tiempo, y...”, luego se detuvo, asombrado en su propia epifania. “Bueno, gracias Tony, eres un querido – mejor Siempre!», concluyó y volvió a corregir el código. Pato de goma La observación que llevó al descubrimiento de la causa raíz fue bastante simple: la solicitud no devolvió en realidad un error de tiempo porque el servidor de la base de datos nunca envió de vuelta una respuesta de este tipo. La solicitud fue simplemente calificada como calificada por el conductor y descartada. pero el único hecho de que el conductor ya no espera una respuesta para una solicitud en particular no significa que la base de datos esté terminando de procesarla! Es totalmente posible que la solicitud estuviera en su lugar simplemente estancada, tomando más tiempo de lo esperado, y sólo el conductor renunció a esperar su respuesta. Con ese conocimiento, es fácil imaginar que una vez que 100 solicitudes estén fuera de tiempo en el lado del cliente, la aplicación podría pensar erróneamente que ya no están en curso, y felicemente envíe 100 más solicitudes a la base de datos, aumentando el número total de solicitudes en vuelo (es decir, concurrencia) a 200. Diario de las lecciones aprendidas de Joan, parte II Las lecciones continúan: Los temporizadores del lado del cliente son convenientes para los programadores, pero pueden interactuar mal con los temporizadores del lado del servidor. Regla del pulgar: haga que los temporizadores del lado del cliente sean alrededor de dos veces más largos que los del lado del servidor, a menos que tenga una razón muy buena para hacer lo contrario. Algunos controladores pueden ser capaces de emitir una advertencia si detectan que el temporizador del lado del cliente es menor que el del lado del servidor, o incluso modifiquen el temporizador del lado del servidor para coincidir, pero en general es mejor hacer una doble comprobación. Las tareas con coincidencias aparentemente fijas pueden causar picos en ciertas condiciones inesperadas.La inspección de registros y dashboards es útil para investigar tales casos, por lo que asegúrese de que las herramientas de observación estén disponibles tanto en el clúster de bases de datos como para todas las aplicaciones de cliente. Con las temporadas del lado del cliente correctamente modificadas, la aplicación se asfixió con mucha menos frecuencia y en una medida menor, pero todavía no era un ciudadano perfecto en el sistema distribuido. De vez en cuando eligió un nodo de base de datos de víctimas y continuó molestándolo con demasiadas solicitudes, mientras ignoraba el hecho de que otros siete nodos estaban considerablemente menos cargados y podían ayudar a manejar la carga de trabajo también. En otras ocasiones, su concurrencia fue reportada para ser exactamente 200% más grande de lo esperado por la configuración. Cuando las dos anomalías convergían en el tiempo, el nodo pobre no podía manejar todas las solicitudes con las que fue bombardeado, y tuvo que renunciar a una parte justa de ellos. formado y mantenido razonablemente actualizado, ayudó a Joan aliviar esos dolores también. El mdbook El primer problema fue simplemente una configuración errónea de la política de equilibrio de carga no predeterminado, que trató demasiado duro para seleccionar el nodo de base de datos "menos cargado" de todos los disponibles, basado en heurísticas y estadísticas actualizadas ocasionalmente por la propia base de datos. Desafortunadamente, esta política también fue “el mejor esfuerzo”, y se basó en el hecho de que las estadísticas que llegan de la base de datos eran siempre legítimas – pero un nodo de base de datos estresado podría volverse tan sobrecargado que no estaba enviando de vuelta las estadísticas actualizadas a tiempo! Esto llevó al conductor a creer falsamente que este servidor en particular no estaba realmente ocupado en absoluto. El segundo problema (doblamiento temporal de la concurrencia) fue causado por otro error de configuración: una política de retiro especulativo excesivo. Después de esperar un período de tiempo preconfigurado sin obtener un reconocimiento de la base de datos, los conductores reenviarían especulativamente una solicitud para maximizar sus posibilidades de éxito. Este mecanismo es muy útil para aumentar la tasa de éxito de las solicitudes. Sin embargo, si la solicitud original también tiene éxito, significa que la solicitud especulativa fue enviada en vano. Para equilibrar los pros y contras, la retiro especulativa debe configurarse para reenviar solo las solicitudes si es muy probable que la original fallara. De lo contrario, como en el caso de Joan, la retiro especulativa puede actuar demasiado pronto, duplicando el número de solicitudes enviadas (y por lo Whew, nada da una prisa simultánea de endorfinas y dopamina como una sesión de desgaste de calidad que termina en un éxito asombroso (excepto escribir una historia cheesy en un libro profundamente técnico, por supuesto). el final. Si lo has conseguido hasta ahora y no puedes obtener suficientes historias de rendimiento de bases de datos, vea lo que le pasó al pobre viejo Patrick en “ “Y si aprecias este sentido del humor, vea el de Piotr. . Editor’s note: Un cuento sobre el rendimiento de la base de datos: Patrick's Unlucky Green Fedoras Nuevo libro sobre la redacción de blogs de ingeniería