Volver a las novedades para desarrolladores

Aprendizajes: Ejecución de Presto a la escala de Meta

11 de abril de 2023DeNeerad Somanchi y Philip Bell

Presto es un motor de consulta SQL gratuito y de código abierto. Lo usamos en Meta durante los últimos diez años y hemos aprendido un montón. Realizar una ejecución a gran escala (ya sea de herramientas, procesos o servicios, por ejemplo) exige habilidades de resolución de problemas para superar los desafíos inesperados. A continuación, te mostramos cuatro lecciones que aprendimos al escalar Presto verticalmente hasta la escala de Meta, y te ofrecemos algunos consejos si te interesa ejecutar tus propias consultas a gran escala.

Escalabilidad rápida de Presto para satisfacer exigencias cada vez mayores: ¿con qué desafíos nos encontramos?

Implementación de nuevas versiones de Presto

Figura 1: Flujo de trabajo del proceso para lanzar nuevas versiones de Presto (diagrama hecho por Philip S. Bell)

Meta ejecuta una gran cantidad de clústeres de Presto que abarcan centros de datos en ubicaciones de todo el mundo. Se desarrolla una nueva versión de Presto que está lista para implementar, aproximadamente, al menos una vez por mes (y, a veces, dos). A medida que la presencia de Presto en Meta crecía rápidamente, uno de los primeros desafíos que enfrentamos fue implementar el motor de consultas en un gran volumen de clústeres y, a la vez, garantizar disponibilidad y confiabilidad de manera constante. Sigue siendo un desafío, en especial, en los casos de uso interactivos de Presto, es decir, cuando un usuario ejecuta una consulta y espera un resultado activamente. Que una consulta falle no es tan grave en los casos de uso "por lotes" automatizados, en los cuales los reintentos automáticos garantizan que la consulta acabe por ejecutarse correctamente.

La solución fue simple. Todos los clústeres de Presto tienen un equilibrador de carga llamado gateway, que es responsable (junto con otros sistemas de Meta) del enrutamiento de las consultas de Presto al clúster correspondiente. Cuando se debe actualizar un clúster de Presto, primero se marca como purgado del gateway, es decir, el gateway deja de enrutar nuevas consultas hacia él. A continuación, la automatización espera un tiempo predeterminado hasta que finalicen las consultas que se están ejecutando en el clúster. Luego se actualiza el clúster y, una vez online, se vuelve visible para el gateway, el cual puede comenzar a enrutar nuevas consultas hacia él.

El otro aspecto de implementar nuevas versiones de Presto es la disponibilidad. Debemos asegurarnos de que los usuarios puedan seguir usando Presto mientras se actualizan los clústeres. De nuevo, la automatización garantiza que todos los centros de datos de todas las regiones físicas tengan siempre el número necesario de clústeres de Presto disponibles. Por supuesto, se debe encontrar un equilibrio entre actualizar demasiados clústeres (problemas de disponibilidad) y actualizar muy pocos a la vez (la implementación lleva mucho tiempo).

Automatización de abandonos y de retiros de clústeres de Presto

Figura 2: Flujo de trabajo automatizado para agregar hardware a los clústeres (diagrama hecho por Philip S. Bell)

La distribución del almacén de datos de Meta en diferentes regiones está en constante evolución. Esto significa que se deben abandonar los nuevos clústeres de Presto mientras los actuales se retiran con regularidad. Antes, cuando solo existían pocos clústeres de Presto, este era un proceso manual. A medida que Meta empezó a escalar verticalmente, se volvió un desafío realizar un seguimiento manual de todos los cambios. Para solucionar este problema, implementamos automatizaciones para gestionar el abandono y el retiro de clústeres.

Primero tuvimos que estandarizar las configuraciones de los clústeres, es decir, crear configuraciones base correspondientes a los distintos casos de uso de Presto en Meta. Cada clúster tenía un número mínimo de especificaciones adicionales o modificadas respecto la configuración base. Una vez completado este paso, se podía activar un nuevo clúster mediante la generación automática de configuraciones a partir de la plantilla base. La activación del clúster también exigía la integración con hooks de automatización para integrar con los diversos servicios de infraestructura de toda la empresa, como Tupperware, y servicios específicos del almacén de datos. Una vez que un clúster está online, se le envían algunas consultas de prueba, y la automatización verifica que el clúster las haya ejecutado correctamente. A continuación, el clúster se registra con el gateway y comienza a ejecutar las consultas.

Retirar un clúster implica el proceso opuesto. Se anula el registro del clúster desde el gateway, y se permite que las consultas en ejecución finalicen. Se cierran los procesos de Presto y se suprimen las configuraciones de los clústeres.

Esta automatización se integra en el flujo de trabajo del abandono y retiro de hardware correspondiente al almacén de datos. El resultado final es la completa automatización de todo el proceso, desde el nuevo hardware que aparece en un centro de datos hasta los clústeres de Presto que están online, ejecutan consultas y luego se cierran cuando se retira el hardware. Con esta implementación, se ahorró tiempo valioso a las personas, se redujo el tiempo de inactividad del hardware y se minimizó la cantidad de errores humanos.

Depuración y resoluciones de problemas automatizadas

Figura 3: Detección de hosts defectuosos (diagrama hecho por Philip S. Bell)

Debido al gran tamaño de la implementación de Presto en Meta, es fundamental que tengamos las herramientas y la automatización correctas para facilitarle la vida al técnico de guardia (la persona de contacto de Presto).

Con los años, creamos diversos "analizadores" que permiten a dicha persona de contacto depurar y evaluar con eficiencia la causa principal de los problemas que surgen. Los sistemas de supervisión activan alertas cuando hay incumplimientos de los acuerdos de nivel de servicio de atención al cliente. Por ende, se activan los analizadores. Derivan la información de una gran variedad de sistemas de supervisión (un almacén de datos operativos u ODS), de eventos publicados en Scuba e, incluso, de registros de nivel de organizador. La lógica personalizada en el analizador une toda esta información para inferir una probable causa principal. Resulta muy útil para la persona de contacto mencionada, ya que se presenta el análisis de la causa principal y se permite pasar directamente a las opciones de mitigación potenciales. En algunos casos, automatizamos por completo tanto la depuración como la resolución de problemas, de modo que ni siquiera se necesita la persona de contacto. A continuación, se describen algunos ejemplos:

Detección de organizador incorrecto

Cuando se ejecutaba Presto a gran escala en muchas máquinas, nos dimos cuenta de que ciertos hosts defectuosos podían causar demasiados errores de consultas. A partir de nuestras investigaciones, identificamos algunas causas principales detrás de los hosts defectuosos, incluidas las siguientes:

  • Problemas de hardware que aún no se habían detectado con los sistemas de supervisión en todas las flotas debido a la falta de cobertura.
  • Errores de JVM desconocidos que, a veces, generaban una secuencia fija de errores de consultas

Para solucionar este problema, ahora supervisamos los errores de consultas en los clústeres de Presto. En concreto, atribuimos cada error de consulta al host que lo causó, si es posible. Además, configuramos alertas que se activan cuando se atribuye un número excepcionalmente alto de errores de consultas a hosts específicos. Entonces, la automatización comienza a purgar el host de la flota de Presto y, así, detiene el aumento de errores.

Depuración de problemas en las colas

Cada clúster de Presto admite poner las consultas en cola una vez que alcanza la concurrencia máxima de ejecución de consultas según el caso de uso, la configuración del hardware y el tamaño de la consulta. En Meta, existe un mecanismo de enrutamiento sofisticado para que se envíe una consulta de Presto al clúster "correcto" que puede ejecutar la consultar y, a la vez, utilizar los recursos de la mejor manera posible. Hay varios sistemas, además de Presto, involucrados en la toma de decisiones relacionadas con el enrutamiento, y tienen en cuenta varios factores:

  • El estado actual de las colas en los clústeres de Presto.
  • La distribución de hardware entre distintos centros de datos.
  • La localidad de datos de las tablas que usa la consulta.

Debido a esta complejidad, puede ser muy difícil que una llamada en curso descubra la causa principal de los problemas de colas que se encuentran en la producción. Este es otro ejemplo en que los analizadores resultan fundamentales, ya que extraen información de varios orígenes y presentan conclusiones.

Solidez del equilibrador de carga

Figura 4: Solidez del equilibrador de carga (diagrama hecho por Philip S. Bell)

Como se mencionó antes, nuestros clústeres de Presto se basan en equilibradores de carga que realizan el enrutamiento de cada consulta de Presto en Meta. Al principio, cuando Presto aún no había escalado verticalmente al nivel de uso interno que tiene hoy, el gateway era muy simple. Sin embargo, a medida que el uso de Presto aumentó en Meta, nos encontramos con problemas de escalabilidad en varias ocasiones. Una de ellas fue que el gateway fallaba por estar sobrecargado, lo que podía hacer que Presto no estuviera disponible para ningún usuario. La causa principal de algunos problemas de estabilidad era que un servicio estaba bombardeando el gateway accidentalmente con millones de consultas en un período corto. En consecuencia, los procesos de gateway se bloqueaban y no podían enrutar las consultas.

Para evitar ese escenario, comenzamos a hacer el gateway más sólido y tolerante a este tráfico imprevisto similar al de un ataque DDoS. Implementamos una función de limitación que rechaza las consultas cuando el gateway está sobrecargado. La limitación se puede activar según un recuento de consultas por segundo en diversas dimensiones, por ejemplo, por usuario, por origen, por IP, y también en de manera global para todas las consultas. Otra mejora que implementamos fue la escalabilidad automática. Gracias al aprendizaje en un servicio en todo Meta que admite la escalabilidad vertical y la reducción horizontal de tareas, el número de instancias de gateway ahora es dinámico. En otras palabras, con una carga pesada, ahora el gateway puede escalar verticalmente para manejar el tráfico adicional y no alcanzar el límite de CPU/memoria, lo que evita el escenario de bloqueo descrito antes. De este modo, junto con la función de limitación, se garantiza que el gateway sea sólido y pueda soportar los patrones de tráfico impredecibles y adversos.

¿Qué consejo le daríamos a un equipo que escala verticalmente su propio almacén de lago de datos mediante Presto?

Figura 5: Escalabilidad de arquitectura de Presto (diagrama hecho por Philip S. Bell)

A continuación, se describen algunos aspectos importantes para tener en cuenta con la escalabilidad vertical de Presto:

  1. Establecer acuerdos de nivel de servicio de atención al cliente bien definidos y fáciles de comprender. A medida que Presto escala verticalmente, resulta fundamental definir los acuerdos de nivel de servicio sobre métricas importantes, como el tiempo en cola y el porcentaje de error de consultas de una manera en que se registren los inconvenientes del cliente. Cuando hay un gran número de usuarios, la falta de acuerdos de nivel de servicio adecuados puede perjudicar los intentos de mitigar los problemas de producción debido a la confusión en cuanto al impacto del incidente.
  2. Supervisión y depuración automática. A medida que Presto escala verticalmente y aumenta el número de clústeres, la supervisión y la depuración automática resultan fundamentales.
    • La supervisión exhaustiva puede ayudar a identificar los problemas de producción antes de que el radio de explosión sea demasiado grande. Detectar los problemas a tiempo garantizará que minimicemos el impacto del usuario siempre que sea posible.
    • Las investigaciones manuales en el contexto de los problemas de producción que afectan al cliente no son escalables. Es fundamental que tengamos la depuración automática como corresponde para que la causa principal se pueda determinar rápido.
  3. Equilibrio de carga correcto. A medida que crece la flota de Presto, es importante tener una solución correcta de equilibrio de carga frente a los clústeres de Presto. A gran escala, las pequeñas deficiencias en el equilibro de carga pueden tener un impacto negativo enorme debido al gran volumen de la carga de trabajo.
  4. Gestión de configuración. La gestión de configuración de una flota grande de clústeres de Presto puede ser un problema si no existe una buena planificación. En la medida de lo posible, las configuraciones deben ser recargables para que las instancias de Presto no tengan que reiniciarse ni actualizarse de manera inesperada, lo que generaría errores de consultas y clientes insatisfechos.

Este artículo se escribió con la colaboración de Neerad Somanchi, ingeniero de producción de Meta, y Philip Bell, desarrollador de Meta.

Para obtener más información sobre Presto, visita prestodb.io, mira la breve explicación de Presto de Philip Bell en YouTube o sigue a Presto en Twitter, Facebook y LinkedIn.

Para obtener más información sobre el código abierto de Meta, visita nuestro sitio de código abierto, suscríbete a nuestro canal de YouTube, o síguenos en Twitter, Facebook y LinkedIn.