Cambiar de Redshift a ClickHouse



Durante mucho tiempo, iFunny usó Redshift como base de datos para eventos que ocurren en servicios de back-end y aplicaciones móviles. Fue elegido porque en el momento de la implementación, en general, no había alternativas comparables en costo y conveniencia.

Sin embargo, todo cambió después del lanzamiento público de ClickHouse. Lo estudiamos durante mucho tiempo, comparamos el costo, estimamos la arquitectura aproximada y, finalmente, este verano decidimos ver qué tan útil es para nosotros. En este artículo, aprenderá sobre el problema que Redshift nos ayudó a resolver y cómo trasladamos esta solución a ClickHouse.

El problema


iFunny necesitaba un servicio similar a Yandex.Metrica, pero exclusivamente para consumo interno. Explicaré por qué.

Los clientes externos escriben eventos. Pueden ser aplicaciones móviles, sitios web o servicios internos de back-end. Es muy difícil para estos clientes explicar que el servicio de recepción de eventos no está disponible actualmente, "intente enviarlo en 15 minutos o en una hora". Hay muchos clientes, quieren enviar eventos todo el tiempo y no pueden esperar en absoluto.

A diferencia de ellos, hay servicios internos y usuarios que son bastante tolerantes a este respecto: pueden funcionar correctamente incluso con un servicio de análisis inaccesible. Y la mayoría de las métricas del producto y los resultados de las pruebas A / B generalmente tienen sentido para ver solo una vez al día, o tal vez incluso con menos frecuencia. Por lo tanto, los requisitos de lectura son bastante bajos. En caso de accidente o actualización, podemos permitirnos ser inaccesibles o inconsistentes en la lectura durante varias horas o incluso días (en un caso particularmente descuidado).

Si hablamos de números, entonces necesitamos tomar alrededor de cinco mil millones de eventos (300 GB de datos comprimidos) por día, mientras almacenamos los datos durante tres meses en una forma "activa" disponible para consultas SQL, y en la "fría" durante dos años. o más, pero para que dentro de unos días podamos convertirlos en "calientes".

Básicamente, los datos son una colección de eventos ordenados por tiempo. Hay alrededor de trescientos tipos de eventos, cada uno tiene su propio conjunto de propiedades. Todavía hay algunos datos de fuentes de terceros que deben sincronizarse con la base de datos analíticos: por ejemplo, una colección de instalaciones de aplicaciones de MongoDB o un servicio externo de AppsFlyer.

Resulta que necesitamos unos 40 TB de disco para la base de datos y unos 250 TB para el almacenamiento "en frío".

Solución Redshift




Por lo tanto, hay clientes móviles y servicios de back-end de los cuales necesita recibir eventos. El servicio HTTP acepta los datos, realiza la validación mínima, recopila eventos en el disco local en archivos agrupados por un minuto, los comprime inmediatamente y los envía al depósito S3. La disponibilidad de este servicio depende de la disponibilidad de los servidores con la aplicación y AWS S3. Las aplicaciones no almacenan estado, por lo que se equilibran, escalan e intercambian fácilmente. S3 es un servicio de almacenamiento de archivos relativamente simple con una buena reputación y disponibilidad, por lo que puede confiar en él.

A continuación, debe entregar de alguna manera los datos a Redshift. Aquí todo es bastante simple: Redshift tiene un importador S3 incorporado, que es la forma recomendada de cargar datos. Por lo tanto, una vez cada 10 minutos, se inicia un script que se conecta a Redshift y le pide que descargue datos utilizando el prefijo s3://events-bucket/main/year=2018/month=10/day=14/10_3*

Para monitorear el estado de la tarea de descarga, utilizamos Apache Airflow : le permite repetir la operación en caso de errores y tener un historial de ejecución claro, lo cual es importante para una gran cantidad de tales tareas. Y en caso de problemas, puede repetir la descarga durante algunos intervalos de tiempo o descargar los datos "en frío" de S3 hace un año.

En el mismo Airflow, de la misma manera, de acuerdo con el cronograma, los scripts funcionan que se conectan a la base de datos y realizan descargas periódicas desde repositorios externos, o construyen agregaciones de eventos en forma de INSERT INTO ... SELECT ...

Redshift tiene garantías débiles de disponibilidad. Una vez a la semana, durante hasta media hora (la ventana de tiempo se especifica en la configuración) AWS puede detener la actualización del clúster o cualquier otro trabajo programado. En el caso de una falla en un nodo, el clúster tampoco estará disponible hasta que se restaure el host. Esto generalmente toma alrededor de 15 minutos y ocurre aproximadamente una vez cada seis meses. En el sistema actual, esto no es un problema, se diseñó originalmente para que la base no estuviera disponible periódicamente.

Bajo Redshift, se utilizaron 4 instancias ds2.8xlarge (36 CPU, 16 TB HDD), lo que en total nos da 64 TB de espacio en disco.

El último punto es la copia de seguridad. La programación de la copia de seguridad se puede especificar en la configuración del clúster y funciona bien.

ClickHouse Transition Motivation


Por supuesto, si no hubiera problemas, nadie hubiera pensado en migrar a ClickHouse. Sin embargo, lo fueron.

Si observa el esquema de almacenamiento ClickHouse con el motor MergeTree y Redshift, puede ver que su ideología es muy similar. Ambas bases de datos son columnares, funcionan bien con una gran cantidad de columnas y comprimen datos en el disco muy bien (y en Redshift puede configurar los tipos de compresión para cada columna individual). Incluso los datos se almacenan de la misma manera: se ordenan por clave primaria, lo que le permite leer solo bloques específicos y no mantener índices individuales en la memoria, y esto es importante cuando se trabaja con grandes cantidades de datos.

La diferencia esencial, como siempre, está en los detalles.

Tabla diaria


La ordenación de datos en el disco y su eliminación en Redshift ocurre cuando usted hace:
 VACUUM <tablename> 
En este caso, el proceso de vacío funciona con todos los datos de esta tabla. Si almacena datos de los tres meses en una tabla, este proceso lleva una cantidad indecente de tiempo y debe realizarlo al menos diariamente, porque los datos antiguos se eliminan y se agregan nuevos. Tuve que crear tablas separadas para cada día y combinarlas a través de la Vista, y esto no es solo la dificultad para rotar y apoyar esta Vista, sino también ralentizar las consultas. A petición, a juzgar por explicar, todas las tablas fueron escaneadas. Y aunque escanear una tabla lleva menos de un segundo, con una cantidad de 90 piezas, resulta que cualquier consulta lleva al menos un minuto. Esto no es muy conveniente.

Duplicados


El siguiente problema son los duplicados. De una forma u otra, al transmitir datos a través de una red, hay dos opciones: perder datos o recibir duplicados. No pudimos perder mensajes, por lo tanto, simplemente nos reconciliamos con el hecho de que algún pequeño porcentaje de eventos se duplicaría. Puede eliminar duplicados por día creando una nueva tabla, insertando datos de la anterior en ella, donde al usar la función de ventana se eliminan las filas con identificación duplicada, la tabla anterior se elimina y la nueva se renombra. Como había una vista en la parte superior de las tablas diarias, era necesario no olvidarse de ella y eliminarla al cambiar el nombre de las tablas. En este caso, también era necesario monitorear los bloqueos, de lo contrario, en el caso de una consulta que bloqueó la vista o una de las tablas, este proceso podría prolongarse durante mucho tiempo.

Monitoreo y mantenimiento.


Ni una sola solicitud en Redshift tarda menos de un par de segundos. Incluso si solo desea agregar un usuario o ver una lista de solicitudes activas, tendrá que esperar un par de decenas de segundos. Por supuesto, puede tolerar, y para esta clase de bases de datos esto es aceptable, pero al final se traduce en un montón de tiempo perdido.

Costo


Según nuestros cálculos, la implementación de ClickHouse en instancias de AWS con exactamente los mismos recursos es exactamente la mitad del precio. Por supuesto, debería ser así, porque al usar Redshift, obtienes una base de datos preparada a la que puedes conectarte con cualquier cliente PostgreSQL inmediatamente después de hacer clic en un par de botones en la consola de AWS, y AWS hará el resto por ti. ¿Pero vale la pena? Ya tenemos la infraestructura, parece que podemos hacer copias de seguridad, monitoreo y configuración, y lo hacemos para un montón de servicios internos. ¿Por qué no abordar el soporte de ClickHouse?

Proceso de transición


Primero, planteamos una pequeña instalación ClickHouse desde una máquina, donde comenzamos periódicamente, utilizando las herramientas integradas, a descargar datos de S3. Por lo tanto, pudimos probar nuestras suposiciones sobre la velocidad y las capacidades de ClickHouse.

Después de un par de semanas de pruebas en una pequeña copia de los datos, quedó claro que para reemplazar Redshift con Clickhouse, se tendrían que resolver varios problemas:

  • sobre qué tipos de instancias y discos para implementar;
  • utilizar la replicación?
  • cómo instalar, configurar y ejecutar;
  • cómo hacer el monitoreo;
  • qué tipo de esquema será;
  • cómo entregar datos desde S3;
  • ¿Cómo reescribir todas las consultas de SQL estándar a no estándar?

Tipos de instancias y discos . En cuanto a la cantidad de procesadores, disco y memoria, decidieron aprovechar la instalación actual de Redshift. Hubo varias opciones, incluidas las instancias i3 con discos NVMe locales, pero decidió detenerse en r5.4xlarge y almacenar en forma de 8T ST1 EBS para cada instancia. Según las estimaciones, esto debería haber dado un rendimiento comparable con Redshift por la mitad del costo. Al mismo tiempo, debido al uso de discos EBS, obtenemos copias de seguridad y recuperación simples a través de instantáneas de discos, casi como en Redshift.

Replicación Como comenzamos desde lo que ya está en Redshift, decidimos no usar la replicación. Además, esto no nos obliga a estudiar de inmediato ZooKeeper, que aún no se encuentra en la infraestructura, pero es genial que ahora sea posible realizar la replicación bajo demanda.

Instalación Esta es la parte más fácil. Un rol lo suficientemente pequeño para Ansible, que instalará paquetes RPM preparados y realizará la misma configuración en cada host.

Monitoreo Para monitorear todos los servicios, Prometheus se usa junto con Telegraf y Grafana, por lo tanto, simplemente ponen agentes de Telegraf en hosts con ClickHouse, recopilan un tablero en Grafana, que muestra la carga actual del servidor por procesador, memoria y discos. A través del complemento de Grafana, llevamos a este panel las solicitudes activas actuales para el clúster, el estado de las importaciones desde S3 y otras cosas útiles. Resultó aún mejor y más informativo (y significativamente más rápido) que el tablero que le dio a la consola de AWS.

Esquema Uno de nuestros principales errores en Redshift fue colocar solo los campos del evento principal en columnas separadas y agregar los campos que rara vez se usan para agregar
en una gran columna de propiedades. Por un lado, esto nos dio flexibilidad para cambiar los campos en las etapas iniciales, cuando no había una comprensión completa de exactamente qué eventos recolectaríamos, con qué propiedades, además, cambiaban 5 veces al día. Y, por otro lado, las solicitudes de una gran columna de propiedades tomaron más y más tiempo. En ClickHouse, decidimos hacer lo correcto de inmediato, por lo que recopilamos todas las columnas posibles e ingresamos el tipo óptimo para ellas. El resultado es una tabla con aproximadamente doscientas columnas.

La siguiente tarea fue elegir el motor adecuado para el almacenamiento y la partición.
No pensaron en volver a particionar, pero hicieron lo mismo que en Redshift: una partición para cada día, pero ahora todas las particiones son una tabla, que
acelera significativamente las solicitudes y simplifica el mantenimiento. El motor de almacenamiento fue tomado por ReplacingMergeTree, ya que le permite eliminar duplicados de una partición particular, simplemente haciendo OPTIMIZE ... FINAL . Además, el esquema de particionamiento diario permite, en caso de errores o accidentes, trabajar solo con datos durante un día, no un mes, que es mucho más rápido.

Entrega de datos desde s3 a ClickHouse . Este fue uno de los procesos más largos. Simplemente no funcionó haciendo la carga mediante las herramientas ClickHouse incorporadas, porque los datos en S3 están en JSON, cada campo debe extraerse en su propio jsonpath, como lo hicimos en Redshift, y a veces también necesitamos usar la transformación: por ejemplo, el UUID de un mensaje de un registro estándar en el formulario DD96C92F-3F4D-44C6-BCD3-E25EB26389E9 convertir a bytes y poner en tipo FixedString (16).

Quería tener un servicio especial similar al que teníamos en Redshift como comando COPY . No encontraron nada listo, así que tuve que hacerlo. Puede escribir un artículo separado sobre cómo funciona, pero en resumen, este es un servicio HTTP implementado en cada host con ClickHouse. Puedes referirte a cualquiera de ellos. Los parámetros de solicitud especifican el prefijo S3 del que se toman los archivos, la lista jsonpath para la conversión de JSON a un conjunto de columnas, así como un conjunto de conversiones para cada columna. El servidor al que llegó la solicitud comienza a escanear archivos en S3 y a distribuir el trabajo de análisis a otros hosts. Al mismo tiempo, es importante para nosotros que las filas que no se pudieron importar, junto con el error, se agreguen a una tabla de ClickHouse separada. Esto ayuda mucho a investigar problemas y errores en el evento que recibe el servicio y los clientes que generan estos eventos. Con la ubicación del importador directamente en los hosts de la base de datos, utilizamos esos recursos, que, por regla general, están inactivos, porque las solicitudes complejas no funcionan las 24 horas. Por supuesto, si hay más solicitudes, siempre puede tomar el servicio del importador para separar los hosts.

No hubo grandes problemas con la importación de datos de fuentes externas. En esos scripts que estaban, simplemente cambiaron el destino de Redshift a ClickHouse.

Había una opción para conectar MongoDB en forma de diccionario y no hacer copias diarias. Desafortunadamente, no encaja, porque el diccionario debe colocarse en la memoria, y el tamaño de la mayoría de las colecciones en MongoDB no lo permite. Pero los diccionarios también nos fueron útiles: usarlos es muy conveniente para conectar bases de datos GeoIP de MaxMind y usar en consultas. Para esto, utilizamos los archivos de diseño ip_trie y CSV que proporciona el servicio. Por ejemplo, la configuración del diccionario geoip_asn_blocks_ipv4 se ve así:

 <dictionaries> <dictionary> <name>geoip_asn_blocks_ipv4</name> <source> <file> <path>GeoLite2-ASN-Blocks-IPv4.csv</path> <format>CSVWithNames</format> </file> <\/source> <lifetime>300</lifetime> <layout> <ip_trie /> </layout> <structure> <key> <attribute> <name>prefix</name> <type>String</type> </attribute> </key> <attribute> <name>autonomous_system_number</name> <type>UInt32</type> <null_value>0</null_value> </attribute> <attribute> <name>autonomous_system_organization</name> <type>String</type> <null_value>?</null_value> </attribute> </structure> </dictionary> </dictionaries> 

Es suficiente poner esta configuración en /etc/clickhouse-server/geoip_asn_blocks_ipv4_dictionary.xml , después de lo cual puede hacer consultas al diccionario para obtener el nombre del proveedor por dirección IP:

 SELECT dictGetString('geoip_asn_blocks_ipv4', 'autonomous_system_organization', tuple(IPv4StringToNum('192.168.1.1'))); 

Cambiar esquema de datos . Como se mencionó anteriormente, decidimos no usar la replicación todavía, ya que ahora podemos permitirnos quedar inaccesibles en caso de accidentes o trabajo planificado, y una copia de los datos ya está en s3 y podemos transferirla a ClickHouse en un período de tiempo razonable. Si no hay replicación, entonces no expandieron ZooKeeper, y la ausencia de ZooKeeper también conduce a la imposibilidad de usar la expresión ON CLUSTER en consultas DDL. Este problema fue resuelto por un pequeño script de Python que se conecta a cada host ClickHouse (solo hay ocho de ellos hasta ahora) y ejecuta la consulta SQL especificada.

Soporte de SQL incompleto en ClickHouse . El proceso de transferencia de solicitudes de la sintaxis Redshift a la sintaxis ClickHouse fue paralela al desarrollo del importador, y fue tratado principalmente por un equipo de analistas. Curiosamente, pero el asunto ni siquiera estaba en JOIN, sino en las funciones de la ventana. Para entender cómo se pueden hacer a través de matrices y funciones lambda, tomó varios días. Es bueno que este problema a menudo esté cubierto en informes sobre ClickHouse, de los cuales hay una gran cantidad, por ejemplo, events.yandex.ru/lib/talks/5420 . En este punto, los datos ya se escribieron a la vez en dos lugares: tanto en Redshift como en el nuevo ClickHouse, por lo que cuando transferimos las solicitudes, comparamos los resultados. Fue problemático comparar la velocidad, ya que eliminamos una gran columna de propiedades, y la mayoría de las consultas comenzaron a funcionar solo con las columnas necesarias, lo que, por supuesto, dio un aumento significativo, pero aquellas consultas en las que la columna de propiedades no participó, funcionaron de la misma manera o un poco más rápido.

Como resultado, obtuvimos el siguiente esquema:



Resultados


En el resultado final, obtuvimos los siguientes beneficios:

  • Una mesa en lugar de 90
  • Las solicitudes de servicio se ejecutan en milisegundos.
  • El costo se ha reducido a la mitad
  • Fácil eliminación de eventos duplicados

También hay desventajas para las que estamos preparados:

  • En caso de accidente, deberá reparar el clúster usted mismo.
  • Los cambios de esquema ahora deben hacerse en cada host por separado
  • La actualización a nuevas versiones tendrá que hacerlo usted mismo.

No podemos comparar la velocidad de las solicitudes de frente, ya que el esquema de datos ha cambiado significativamente. Muchas consultas se han vuelto más rápidas, simplemente porque leen menos datos del disco. En el buen sentido, dicho cambio tuvo que hacerse de nuevo en Redshift, pero se decidió combinarlo con la migración a ClickHouse.

Toda la migración junto con la preparación tomó alrededor de tres meses. Caminó desde principios de julio hasta finales de septiembre y exigió la participación de dos personas. 27 de septiembre, apagamos Redshift y desde entonces hemos estado trabajando solo en ClickHouse. Resulta que ya hace poco más de dos meses. El término es corto, pero hasta ahora nunca ha encontrado una pérdida de datos o un error crítico, por lo que todo el clúster se levantaría. ¡Delante de nosotros estamos esperando actualizaciones sobre nuevas versiones!

Source: https://habr.com/ru/post/es433346/


All Articles