ClickHouse para usuarios avanzados en preguntas e respostas

En abril, os enxeñeiros de Avito reuníronse para reunións en liña co desenvolvedor principal de ClickHouse Alexey Milovidov e Kirill Shvakov, un desenvolvedor de Golang de Integros. Comentamos como usamos un sistema de xestión de bases de datos e que dificultades atopamos.

A partir da reunión, compilamos un artigo coas respostas dos expertos ás preguntas da nosa e da audiencia sobre copias de seguranza, redistribución de datos, dicionarios externos, controlador Golang e actualización de versións de ClickHouse. Pode ser útil para desenvolvedores que xa están a traballar activamente co DBMS Yandex e están interesados ​​no seu presente e futuro. Por defecto, as respostas son de Alexey Milovidov, a non ser que se escriba o contrario.

Teña coidado, hai moito texto baixo o corte. Agardamos que o contido con preguntas che axude a navegar.

ClickHouse para usuarios avanzados en preguntas e respostas

Contido

Se non queres ler o texto, podes ver a gravación das tertulias na nosa canle de YouTube. Os códigos de tempo están no primeiro comentario baixo o vídeo.

ClickHouse actualízase constantemente, pero os nosos datos non. Que facer ao respecto?

ClickHouse actualízase constantemente e os nosos datos, que foron optimizados ao final do procesado, non se actualizan e están nunha copia de seguridade.

Digamos que tivemos algún problema e que se perderon os datos. Decidimos restaurar, e resultou que as particións antigas, que se almacenan nos servidores de copia de seguridade, son moi diferentes da versión de ClickHouse que se usa actualmente. Que facer ante tal situación, e é posible?

Unha situación na que restauras os datos dunha copia de seguridade nun formato antigo, pero non se conecta á nova versión, é imposible. Asegurámonos de que o formato de datos en ClickHouse sempre sexa compatible con versións anteriores. Isto é moito máis importante que a compatibilidade con versións anteriores na funcionalidade se cambiou o comportamento dalgunha función que raramente se usa. A nova versión de ClickHouse sempre debería poder ler os datos almacenados no disco. Esta é a lei.

Cales son as prácticas recomendadas actuais para facer copias de seguranza dos datos de ClickHouse?

Como facer copias de seguridade, tendo en conta que temos optimizar as operacións finais, unha enorme base de datos de terabytes e datos que se actualizan, digamos, durante os últimos tres días, e logo non lle ocorren trámites?

Podemos facer a nosa propia solución e escribir no bash: recoller estas copias de seguridade de tal ou cal xeito. Quizais non hai que muleta nada, e a bicicleta foi inventada hai moito tempo?

Comecemos coas mellores prácticas. Os meus compañeiros sempre aconsellan, en resposta a preguntas sobre copias de seguridade, lembrarlles o servizo Yandex.Cloud, onde xa se solucionou este problema. Así que úsao se é posible.

Non hai unha solución completa para as copias de seguridade, integrada ao cen por cento en ClickHouse. Hai algúns espazos en branco que se poden usar. Para obter unha solución completa, terás que retocar un pouco manualmente ou crear envoltorios en forma de scripts.

Empezarei polas solucións máis sinxelas e rematarei coas máis sofisticadas, dependendo do volume de datos e do tamaño do clúster. Canto máis grande é o clúster, máis complexa se fai a solución.

Se a táboa con datos ocupa só uns gigabytes, a copia de seguridade pódese facer deste xeito:

  1. Gardar definición da táboa, é dicir, metadatos − mostrar crear táboa.
  2. Fai un volcado usando o cliente ClickHouse - seleccionar * da mesa para arquivar. Por defecto, recibirá un ficheiro en formato separado por tabulacións. Se queres ser máis eficiente, podes facelo en formato Nativo.

Se a cantidade de datos é maior, a copia de seguridade levará máis tempo e moito espazo. Isto chámase copia de seguridade lóxica; non está vinculada ao formato de datos ClickHouse. Se é así, como último recurso podes facer unha copia de seguridade e cargala en MySQL para a súa recuperación.

Para casos máis avanzados, ClickHouse ten unha capacidade integrada para crear unha instantánea de particións no sistema de ficheiros local. Esta función está dispoñible como solicitude modificar a partición de conxelación da táboa. Ou simplemente alterar a conxelación da mesa - Esta é unha instantánea de toda a táboa.

A instantánea crearase de forma consistente para unha táboa nun fragmento, é dicir, é imposible crear unha instantánea consistente de todo o clúster deste xeito. Pero para a maioría das tarefas non hai tal necesidade, e abonda con executar unha solicitude en cada fragmento e obter unha instantánea consistente. Créase en forma de ligazóns duras e, polo tanto, non ocupa espazo adicional. A continuación, copia esta instantánea no servidor de copia de seguranza ou no almacenamento que utiliza para realizar copias de seguranza.

Restaurar unha copia de seguridade deste tipo é bastante sinxelo. En primeiro lugar, cree táboas utilizando as definicións de táboa existentes. A continuación, copie as instantáneas gardadas das particións en Directory-Detached para estas táboas e execute a consulta conectar partición. Esta solución é moi adecuada para os volumes de datos máis serios.

Ás veces necesitas algo aínda máis xenial, nos casos nos que tes decenas ou mesmo centos de terabytes en cada servidor e centos de servidores. Aquí hai unha solución que collín dos meus compañeiros de Yandex.Metrica. Non llo recomendaría a todos: léao e decide por ti mesmo se é axeitado ou non.

Primeiro cómpre crear varios servidores con estantes de discos grandes. A continuación, nestes servidores, levante varios servidores ClickHouse e configúreos para que funcionen como outra réplica para os mesmos fragmentos. E despois usa un sistema de ficheiros ou algunha ferramenta nestes servidores que che permita crear instantáneas. Aquí hai dúas opcións. A primeira opción son as instantáneas LVM, a segunda opción é ZFS en Linux.

Despois diso, todos os días necesitas crear unha instantánea, mentirá e ocupará espazo. Por suposto, se os datos cambian, a cantidade de espazo aumentará co paso do tempo. Esta instantánea pódese sacar en calquera momento e restaurar os datos, unha solución tan estraña. Ademais, tamén temos que limitar estas réplicas na configuración para que non intenten converterse en líderes.

Será posible organizar un atraso controlado de réplicas nos fustes?

Este ano planeas facer eixos en ClickHouse. Será posible organizar nelas un atraso controlado de réplicas? Gustaríanos usalo para protexernos de escenarios negativos con alteracións e outros cambios.

É posible facer algún tipo de retroceso para alterar? Por exemplo, nun eixe existente, toma e di que ata este momento aplicas os cambios, e a partir deste momento deixas de aplicar os cambios?

Se un comando chegou ao noso clúster e rompíao, entón temos unha réplica condicional cunha hora de atraso, onde podemos dicir que imos usalo no momento, pero non lle aplicaremos cambios durante os últimos dez minutos?

En primeiro lugar, sobre o atraso controlado das réplicas. Houbo unha solicitude deste tipo de usuarios e creamos un problema en Github coa solicitude: "Se alguén necesita isto, gústalle, pon un corazón". Ninguén entregou e o problema foi pechado. Non obstante, xa podes ter esta oportunidade configurando ClickHouse. É certo, só a partir da versión 20.3.

ClickHouse realiza constantemente a fusión de datos en segundo plano. Cando se completa unha fusión, un determinado conxunto de datos substitúese por outro máis grande. Ao mesmo tempo, os datos que estaban alí antes seguen permanecendo no disco durante algún tempo.

En primeiro lugar, continúan gardándose mentres haxa consultas seleccionadas que as utilicen, para proporcionar unha operación sen bloqueo. As consultas seleccionadas lense facilmente desde anacos antigos.

En segundo lugar, tamén hai un limiar de tempo: os datos antigos están no disco durante oito minutos. Estes oito minutos pódense personalizar e incluso converter nun só día. Isto custará espazo no disco: dependendo do fluxo de datos, resulta que no último día os datos non só se duplicarán, senón que poderían chegar a ser cinco veces máis. Pero se hai un problema grave, pode deter o servidor ClickHouse e resolver todo.

Agora xorde a pregunta de como isto protexe contra alteracións. Paga a pena botar unha ollada máis profunda aquí, porque nas versións antigas de ClickHouse, o alter funcionaba de tal xeito que simplemente cambiaba pezas directamente. Hai un dato con algúns ficheiros, e nós, por exemplo, alterar a columna de caída. A continuación, esta columna elimínase fisicamente de todos os anacos.

Pero a partir da versión 20.3, o mecanismo de modificación cambiouse por completo e agora os datos son sempre inmutables. Non cambian en absoluto; agora os cambios funcionan do mesmo xeito que as fusións. En lugar de substituír unha peza no lugar, creamos unha nova. No novo fragmento, os ficheiros que non cambiaron convértense en enlaces duros, e se eliminamos unha columna, simplemente faltará no novo fragmento. A peza antiga eliminarase de forma predeterminada despois de oito minutos, e aquí podes modificar a configuración mencionada anteriormente.

O mesmo aplícase a alteracións como as mutacións. Cando o fas modificar eliminar ou alterar a actualización, non cambia a peza, senón que crea unha nova. E despois borra o antigo.

E se a estrutura da táboa cambiou?

Como restaurar unha copia de seguridade que se fixo co esquema antigo? E a segunda pregunta é sobre o caso das instantáneas e as ferramentas do sistema de ficheiros. Btrfs é bo aquí en lugar de ZFS en Linux LVM?

Se o fas conectar partición particións cunha estrutura diferente, entón ClickHouse dirá que isto non é posible. Esta é a solución. O primeiro é crear unha táboa temporal do tipo MergeTree coa estrutura antiga, anexar datos alí usando attach e facer unha consulta de modificación. A continuación, pode copiar ou transferir estes datos e anexar de novo, ou utilizar unha solicitude alterar a mesa mover a partición.

Agora a segunda pregunta é se se pode usar Btrfs. Para comezar, se tes LVM, as instantáneas de LVM son suficientes e o sistema de ficheiros pode ser ext4, non importa. Con Btrts, todo depende da túa experiencia no seu uso. Este é un sistema de ficheiros maduro, pero aínda hai algunhas sospeitas sobre como funcionará todo na práctica nun escenario particular. Non recomendaría usar isto a menos que teñas Btrfs en produción.

Cales son as mellores prácticas actuais en materia de redistribución de datos?

O tema do reparto é complexo e multifacético. Aquí hai varias respostas posibles. Podes ir dun lado e dicir isto: ClickHouse non ten unha función de redistribución integrada. Pero temo que esta resposta non lle convén a ninguén. Polo tanto, pode ir dende o outro lado e dicir que ClickHouse ten moitas formas de redistribuír os datos.

Se o clúster queda sen espazo ou non pode xestionar a carga, engade novos servidores. Pero estes servidores están baleiros por defecto, non hai datos neles, non hai carga. Debes reorganizar os datos para que estean repartidos uniformemente polo novo clúster máis grande.

A primeira forma que se pode facer é copiar parte das particións a novos servidores mediante unha solicitude alterar a partición de recuperación da táboa. Por exemplo, tiñas particións por mes e tomas o primeiro mes de 2017 e cópiao nun servidor novo e despois copia o terceiro mes noutro servidor novo. E fai isto ata que se fai máis ou menos uniforme.

A transferencia só se pode realizar para aquelas particións que non cambian durante a gravación. Para particións novas, a gravación terá que estar desactivada, porque a súa transferencia non é atómica. En caso contrario, acabarás con duplicados ou lagoas nos datos. Non obstante, este método é práctico e funciona de forma bastante eficaz. As particións comprimidas xa preparadas transmítense pola rede, é dicir, os datos non se comprimen nin se codifican de novo.

Este método ten un inconveniente, e depende do esquema de fragmentación, se se comprometeu con este esquema de fragmentación, a clave de fragmentación que tiña. No teu exemplo para o caso das métricas, a clave de fragmentación é o hash do camiño. Cando selecciona unha táboa distribuída, vai a todos os fragmentos do clúster á vez e toma datos de alí.

Isto significa que en realidade non che importa que datos acabaron en que fragmento. O principal é que os datos dun camiño acaban nun fragmento, pero cal non é importante. Neste caso, a transferencia de particións preparadas é perfecta, xa que con consultas seleccionadas tamén recibirás datos completos, xa sexa antes da redistribución ou despois, o esquema realmente non importa.

Pero hai casos que son máis complexos. Se a nivel lóxico da aplicación confía nun esquema especial de fragmentación, que este cliente está situado en tal ou cal fragmento, e a solicitude pódese enviar directamente alí e non á táboa Distribuída. Ou estás usando unha versión bastante recente de ClickHouse e activaches a configuración optimizar omitir fragmentos non utilizados. Neste caso, durante a consulta de selección, analizarase a expresión da sección onde e calcularase que fragmentos hai que utilizar segundo o esquema de fragmentación. Isto funciona sempre que os datos se particionen exactamente segundo este esquema de fragmentación. Se os reorganizaches manualmente, a correspondencia pode cambiar.

Polo tanto, este é o método número un. E estou á espera da túa resposta, se o método é axeitado ou seguimos adiante.

Vladimir Kolobaev, administrador principal do sistema en Avito: Alexey, o método que mencionaches non funciona moi ben cando necesitas repartir a carga, incluída a lectura. Podemos levar unha partición que sexa mensual e pode levar o mes anterior a outro nodo, pero cando chegue unha solicitude destes datos, só cargaremos. Pero gustaríanos cargar todo o clúster, porque se non, durante algún tempo toda a carga de lectura será procesada por dous fragmentos.

Alexey Milovidov: A resposta aquí é estraña: si, é malo, pero pode funcionar. Vou explicar exactamente como. Paga a pena mirar o escenario de carga que hai detrás dos teus datos. Se se trata de datos de seguimento, case con toda seguridade podemos dicir que a gran maioría das solicitudes son datos novos.

Instalaches novos servidores, migraches particións antigas, pero tamén cambiaches como se rexistran os datos novos. E os datos novos espallaranse por todo o clúster. Así, despois de só cinco minutos, as solicitudes dos últimos cinco minutos cargarán o clúster de xeito uniforme; despois dun día, as solicitudes de XNUMX horas cargarán o clúster de xeito uniforme. E as solicitudes do mes anterior, por desgraza, só irán a parte dos servidores do clúster.

Pero moitas veces non terás solicitudes específicas para febreiro de 2019. Probablemente, se as solicitudes entran en 2019, serán para todo o 2019, durante un gran período de tempo e non para un pequeno intervalo. E tales solicitudes tamén poderán cargar o clúster de xeito uniforme. Pero, en xeral, a túa observación é absolutamente correcta de que se trata dunha solución ad hoc que non difunde os datos de forma completamente uniforme.

Teño algúns puntos máis para responder á pregunta. Un deles trata sobre como deseñar inicialmente un esquema de fragmentación para que o re-sharding cause menos dor. Isto non sempre é posible.

Por exemplo, tes datos de seguimento. Os datos de seguimento están crecendo por tres razóns. O primeiro é a acumulación de datos históricos. O segundo é o crecemento do tráfico. E o terceiro é o aumento do número de cousas que están sometidas a vixilancia. Hai novos microservizos e métricas que hai que gardar.

É posible que deles, o maior aumento estea asociado coa terceira razón: o aumento do uso da vixilancia. E neste caso, paga a pena mirar a natureza da carga, cales son as principais consultas seleccionadas. As consultas de selección básicas probablemente se baseen nalgún subconxunto de métricas.

Por exemplo, o uso da CPU nalgúns servidores por algún servizo. Resulta que hai un determinado subconxunto de claves polas que obtén estes datos. E a propia solicitude destes datos probablemente sexa bastante sinxela e se complete en decenas de milisegundos. Úsase para servizos de monitorización e paneis de control. Espero entender isto correctamente.

Vladimir Kolobaev: O caso é que con moita frecuencia apelamos a datos históricos, xa que comparamos a situación actual coa histórica en tempo real. E é importante para nós ter acceso rápido a unha gran cantidade de datos, e ClickHouse fai un excelente traballo con isto.

Tes toda a razón, experimentamos a maioría das solicitudes de lectura no último día, como calquera sistema de seguimento. Pero ao mesmo tempo, a carga dos datos históricos tamén é bastante grande. Básicamente é dun sistema de alertas que pasa cada trinta segundos e di a ClickHouse: “Dáme os datos das últimas seis semanas. Agora constrúeme algún tipo de media móbil a partir deles e comparemos o valor actual co histórico".

Gustaríame dicir que para solicitudes tan recentes temos outra pequena táboa na que só almacenamos dous días de datos, e as principais solicitudes voan para ela. Só enviamos consultas históricas grandes á táboa dividida grande.

Alexey Milovidov: Desafortunadamente, resulta ser pouco aplicable ao teu escenario, pero contareiche unha descrición de dous esquemas de fragmentación malos e complexos que non é necesario utilizar, pero que se utilizan no servizo dos meus amigos.

Hai un clúster principal con eventos Yandex.Metrica. Os eventos son páxinas vistas, clics e conversións. A maioría das solicitudes van a un sitio web específico. Abre o servizo Yandex.Metrica, tes un sitio web - avito.ru, vai ao informe e fai unha solicitude para o teu sitio web.

Pero hai outras peticións -analíticas e globais- que son realizadas por analistas internos. Por se acaso, observo que os analistas internos fan solicitudes só para servizos Yandex. Pero, con todo, incluso os servizos de Yandex ocupan unha parte importante de todos os datos. Estas son solicitudes non para contadores específicos, senón para un filtrado máis amplo.

Como organizar os datos de forma que todo funcione de forma eficiente para un contador e tamén para consultas globais? Outra dificultade é que o número de solicitudes en ClickHouse para o clúster de métricas é de varios miles por segundo. Ao mesmo tempo, un servidor ClickHouse non pode xestionar solicitudes non triviais, por exemplo, varios miles por segundo.

O tamaño do clúster é de seiscentos servidores. Se simplemente tiras dunha táboa distribuída sobre este clúster e envías alí varios miles de solicitudes, será aínda peor que envialas a un servidor. Por outra banda, a opción de que os datos estean repartidos uniformemente, e imos a solicitar desde todos os servidores, descártase inmediatamente.

Hai unha opción que é diametralmente oposta. Imaxina se repartimos os datos entre sitios e unha solicitude dun sitio vai a un fragmento. Agora o clúster poderá xestionar dez mil solicitudes por segundo, pero nun fragmento calquera solicitude funcionará demasiado lentamente. Xa non escalará en termos de rendemento. Especialmente se este é o sitio avito.ru. Non desvelarei o segredo se digo que Avito é un dos sitios máis visitados de RuNet. E procesala nun fragmento sería unha tolemia.

Polo tanto, o esquema de fragmentación está deseñado dun xeito máis astuto. Todo o cluster está dividido nunha serie de clusters, que chamamos capas. Cada clúster contén dende unha ducia ata varias ducias de fragmentos. Hai trinta e nove agrupacións deste tipo en total.

Como escala todo isto? O número de clústeres non cambia, como hai trinta e nove anos, segue a ser. Pero dentro de cada un deles, aumentamos gradualmente o número de fragmentos a medida que acumulamos datos. E o esquema de fragmentación no seu conxunto é así: estes clústeres están divididos en sitios web e, para comprender que sitio web está en que clúster, utilízase unha metabase separada en MySQL. Un sitio - nun cluster. E no seu interior, prodúcese a fragmentación segundo as identificacións dos visitantes.

Ao gravar, dividímolos polo resto da división do ID do visitante. Pero ao engadir un novo fragmento, o esquema de fragmentación cambia; seguimos dividindo, pero cun resto da división por outro número. Isto significa que un visitante xa está situado en varios servidores e non pode confiar nel. Isto faise unicamente para garantir que os datos estean mellor comprimidos. E ao facer solicitudes, imos á táboa Distribuída, que mira o clúster e accede a decenas de servidores. Este é un esquema tan estúpido.

Pero a miña historia quedará incompleta se non digo que abandonamos este esquema. No novo esquema, cambiamos todo e copiamos todos os datos usando clickhouse-copier.

No novo esquema, todos os sitios divídense en dúas categorías: grandes e pequenos. Non sei como se escolleu o limiar, pero o resultado foi que os sitios grandes son rexistrados nun clúster, onde hai 120 fragmentos con tres réplicas cada un, é dicir, 360 servidores. E o esquema de fragmentación é tal que calquera solicitude vai a todos os fragmentos á vez. Se agora abres calquera páxina de informes para avito.ru en Yandex.Metrica, a solicitude irá a 120 servidores. Hai poucos sitios grandes en RuNet. E as peticións non son de mil por segundo, senón de menos de cen. Todo isto é mastigado tranquilamente pola táboa Distribuída, que cada unha delas procesa con 120 servidores.

E o segundo clúster é para sitios pequenos. Aquí tes un esquema de fragmentación baseado no ID do sitio, e cada solicitude vai a exactamente un fragmento.

ClickHouse ten unha utilidade clickhouse-copiadora. Podes falarnos dela?

Direi de inmediato que esta solución é máis engorrosa e algo menos produtiva. A vantaxe é que mancha os datos completamente segundo o patrón que especifique. Pero o inconveniente da utilidade é que non se recarga en absoluto. Copia os datos dun esquema de clúster a outro esquema de clúster.

Isto significa que para que funcione debes ter dous clusters. Poden situarse nos mesmos servidores, pero, con todo, os datos non se moverán de forma incremental, senón que se copiarán.

Por exemplo, había catro servidores, agora son oito. Crea unha nova táboa distribuída en todos os servidores, novas táboas locais e inicia clickhouse-copier, indicando nela o esquema de traballo que debe ler a partir de aí, acepta o novo esquema de fragmentación e transfire os datos alí. E nos servidores antigos necesitarás unha vez e media máis espazo do que hai agora, porque os datos antigos deben permanecer neles, e a metade dos mesmos datos antigos chegarán encima deles. Se pensas de antemán que hai que redistribuír os datos e hai espazo, entón este método é adecuado.

Como funciona o clickhouse-copier dentro? Divide todo o traballo nun conxunto de tarefas para procesar unha partición dunha táboa nun fragmento. Todas estas tarefas pódense executar en paralelo, e clickhouse-copier pódese executar en diferentes máquinas en varias instancias, pero o que fai para unha partición non é máis que unha selección de inserción. Os datos son lidos, descomprimidos, reparticionados, comprimidos de novo, escríbense nalgún lugar e reordenan. Esta é unha decisión máis difícil.

Tiveches unha cousa piloto chamada resharding. Que con ela?

En 2017, tiveches unha cousa piloto chamada resharding. Incluso hai unha opción en ClickHouse. Segundo entendo, non despegou. Podes dicirme por que pasou isto? Parece que é moi relevante.

Todo o problema é que se é necesario redistribuír os datos no seu lugar, é necesaria unha sincronización moi complexa para facelo atómicamente. Cando comezamos a ver como funciona esta sincronización, quedou claro que había problemas fundamentais. E estes problemas fundamentais non son só teóricos, senón que inmediatamente comezaron a mostrarse na práctica en forma de algo que se pode explicar de forma moi sinxela: nada funciona.

É posible combinar todos os datos antes de movelos a discos lentos?

Pregunta sobre TTL coa opción de mover ao disco lento no contexto das fusións. Hai algún xeito, que non sexa a través de cron, de combinar todas as partes nunha soa antes de movelas a discos lentos?

A resposta á pregunta é posible pegar automaticamente todas as pezas nunha soa antes de transferila - non. Non creo que isto sexa necesario. Non tes que fusionar todas as partes nunha soa, senón que simplemente contas co feito de que se transferirán a discos lentos automaticamente.

Temos dous criterios para as regras de transferencia. O primeiro é tal e como está cheo. Se o nivel de almacenamento actual ten menos dunha determinada porcentaxe de espazo libre, seleccionamos un anaco e movémolo a un almacenamento máis lento. Ou mellor dito, non máis lento, senón o seguinte, segundo o configures.

O segundo criterio é o tamaño. Trátase de mover pezas grandes. Podes axustar o limiar segundo o espazo libre no disco rápido e os datos transferiranse automaticamente.

Como migrar a novas versións de ClickHouse se non hai forma de comprobar a compatibilidade con antelación?

Este tema é discutido regularmente no chat de telegrama de ClickHouse tendo en conta diferentes versións, e aínda. Que seguro é actualizar da versión 19.11 á 19.16 e, por exemplo, da 19.16 á 20.3. Cal é a mellor forma de migrar a novas versións sen poder comprobar previamente a compatibilidade no sandbox?

Aquí hai varias regras "de ouro". Primeira - ler o rexistro de cambios. É grande, pero hai parágrafos separados sobre cambios incompatibles cara atrás. Non trates estes puntos como unha bandeira vermella. Normalmente son incompatibilidades menores que implican algunha funcionalidade de borde que moi probablemente non use.

En segundo lugar, se non hai forma de comprobar a compatibilidade no sandbox e queres actualizar inmediatamente en produción, a recomendación é que non teñas que facelo. Primeiro crea unha caixa de area e proba. Se non hai un ambiente de proba, é probable que non teña unha empresa moi grande, o que significa que pode copiar algúns dos datos no seu portátil e asegurarse de que todo funciona correctamente nel. Incluso pode crear varias réplicas localmente na súa máquina. Ou podes coller unha nova versión nalgún lugar preto e cargar alí algúns dos datos, é dicir, crear un ambiente de proba improvisado.

Outra regra é non actualizar durante unha semana despois do lanzamento da versión debido a que se detectan erros na produción e as correccións rápidas posteriores. Imos descubrir a numeración das versións de ClickHouse para non confundirnos.

Existe a versión 20.3.4. O número 20 indica o ano de fabricación - 2020. Dende o punto de vista do que hai dentro, isto non importa, polo que non lle prestaremos atención. Seguinte - 20.3. Aumentamos o segundo número, neste caso 3, cada vez que lanzamos unha versión con algunha funcionalidade nova. Se queremos engadir algunha función a ClickHouse, debemos aumentar este número. É dicir, na versión 20.4 ClickHouse funcionará aínda mellor. O terceiro díxito é 20.3.4. Aquí 4 é o número de lanzamentos de parches nos que non engadimos novas funcións, pero solucionamos algúns erros. E 4 significa que o fixemos catro veces.

Non penses que isto é algo terrible. Normalmente o usuario pode instalar a versión máis recente e funcionará sen problemas co tempo de actividade ao ano. Pero imaxina que nalgunha función para procesar mapas de bits, que foron engadidas polos nosos compañeiros chineses, o servidor falla ao pasar argumentos incorrectos. Temos a responsabilidade de solucionar isto. Lanzaremos unha nova versión do parche e ClickHouse farase máis estable.

Se tes ClickHouse en produción e se publica unha nova versión de ClickHouse con funcións adicionais, por exemplo, 20.4.1 é a primeira, non te apresures a poñela en produción o primeiro día. Por que é necesario? Se aínda non usas ClickHouse, podes instalalo e, moi probablemente, todo estará ben. Pero se ClickHouse xa funciona de forma estable, manteña un ollo nos parches e actualizacións para ver que problemas estamos a solucionar.

Kirill Shvakov: Gustaríame engadir un pouco sobre os ambientes de proba. Todo o mundo ten moito medo aos ambientes de proba e, por algún motivo, cren que se tes un clúster ClickHouse moi grande, o ambiente de proba non debería ser menos ou polo menos dez veces máis pequeno. Non é así en absoluto.

Podo dicirche polo meu propio exemplo. Teño un proxecto, e hai ClickHouse. O noso ambiente de proba é só para el: trátase dunha pequena máquina virtual en Hetzner por vinte euros, onde se desprega absolutamente todo. Para iso, temos unha automatización total en Ansible e, polo tanto, en principio, non importa onde ir: aos servidores de hardware ou só a implementar en máquinas virtuais.

Que se pode facer? Sería bo proporcionar un exemplo na documentación de ClickHouse sobre como implementar un pequeno clúster na túa propia casa: en Docker, en LXC, quizais crees un manual de xogos de Ansible, porque diferentes persoas teñen diferentes implementacións. Isto simplificará moito. Cando tomas e implantas un clúster en cinco minutos, é moito máis fácil tentar descubrir algo. Isto é moito máis cómodo, porque incorporarse a unha versión de produción que non probaches é un camiño cara a ningunha parte. Ás veces funciona e ás veces non. E polo tanto, esperar o éxito é malo.

Maxim Kotyakov, enxeñeiro senior de backend Avito: Engaderei un pouco sobre os ambientes de proba dunha serie de problemas aos que se enfrontan as grandes empresas. Temos un clúster de aceptación de ClickHouse completo; en termos de esquemas de datos e configuración, é unha copia exacta do que está en produción. Este clúster está implantado en contedores bastante deteriorados cun mínimo de recursos. Escribimos unha determinada porcentaxe dos datos de produción alí, afortunadamente é posible replicar o fluxo en Kafka. Todo aí está sincronizado e escalado, tanto en termos de capacidade como de fluxo, e, en teoría, sendo todas as demais cousas iguais, debería comportarse como produción en termos de métricas. Todo o que sexa potencialmente explosivo enróllase primeiro neste soporte e déixase alí durante varios días ata que estea listo. Pero, naturalmente, esta solución é cara, difícil e ten custos de soporte distintos de cero.

Alexey Milovidov: Vouche dicir como é o ambiente de proba dos nosos amigos de Yandex.Metrica. Un clúster tiña uns 600 servidores, outro tiña 360 e hai un terceiro e varios clústeres. O ambiente de proba para un deles son simplemente dous fragmentos con dúas réplicas en cada un. Por que dous cacos? Para que non esteas só. E tamén debería haber réplicas. Só unha determinada cantidade mínima que pode pagar.

Este ambiente de proba permíteche comprobar se as túas consultas funcionan e se hai algún problema importante. Pero moitas veces xorden problemas de natureza completamente diferente, cando todo funciona, pero hai algúns pequenos cambios na carga.

Déixame un exemplo. Decidimos instalar unha nova versión de ClickHouse. Publicouse nun ambiente de proba, realizáronse probas automatizadas no propio Yandex.Metrica, que comparan datos da versión antiga e da nova, executando todo o pipeline. E por suposto, probas verdes do noso CI. Se non, nin sequera teriamos proposto esta versión.

Todo está ben. Estamos empezando a pasar á produción. Recibo unha mensaxe de que a carga dos gráficos aumentou varias veces. Revertimos a versión. Miro o gráfico e vexo: a carga en realidade aumentou varias veces durante o lanzamento e diminuíu cando se lanzaron. Entón comezamos a revertir a versión. E a carga aumentou do mesmo xeito e retrocedeu do mesmo xeito. Entón, a conclusión é a seguinte: a carga aumentou debido ao deseño, nada sorprendente.

Entón foi difícil convencer aos compañeiros de instalar a nova versión. Eu digo: "Está ben, desenrola. Manteña os dedos cruzados, todo funcionará. Agora aumentou a carga dos gráficos, pero todo está ben. Aguanta aí". En xeral, fixemos isto, e iso é todo: a versión foi lanzada para a produción. Pero case con todas as disposicións xorden problemas similares.

Suponse que Kill query elimina as consultas, pero non o fai. Por que?

Un usuario, unha especie de analista, veu a min e creou unha solicitude que puxo o meu clúster ClickHouse. Algún nodo ou clúster completo, dependendo de a que réplica ou fragmento se dirixiu a solicitude. Vexo que todos os recursos da CPU deste servidor están nun estante, todo é vermello. Ao mesmo tempo, a propia ClickHouse responde ás solicitudes. E escribo: "Por favor, móstrame, lista de procesos, que solicitude xerou esta loucura".

Atopo esta solicitude e escríboa kill. E vexo que non pasa nada. O meu servidor está nun estante, ClickHouse dáme algúns comandos, mostra que o servidor está vivo e todo é xenial. Pero teño degradación en todas as solicitudes dos usuarios, a degradación comeza cos rexistros en ClickHouse e a miña consulta de eliminación non funciona. Por que? Pensei que kill query debía matar as consultas, pero non é así.

Agora haberá unha resposta bastante estraña. A cuestión é que a consulta de matar non mata as consultas.

Matar a consulta marca unha pequena caixa chamada "Quero que se elimine esta consulta". E a propia solicitude mira esta bandeira ao procesar cada bloque. Se está configurado, a solicitude deixa de funcionar. Resulta que ninguén mata a solicitude, el mesmo debe comprobar todo e parar. E isto debería funcionar en todos os casos en que a solicitude estea en estado de procesamento de bloques de datos. Procesará o seguinte bloque de datos, comprobará a bandeira e parará.

Isto non funciona nos casos en que a solicitude está bloqueada nalgunha operación. É certo, o máis probable é que este non sexa o teu caso, porque, segundo ti, utiliza unha tonelada de recursos do servidor. É posible que isto non funcione no caso da clasificación externa e nalgúns outros detalles. Pero en xeral isto non debería ocorrer, é un erro. E o único que podo recomendar é actualizar ClickHouse.

Como calcular o tempo de resposta baixo a carga de lectura?

Hai unha táboa que almacena os agregados de elementos: varios contadores. O número de liñas é de aproximadamente cen millóns. É posible contar cun tempo de resposta previsible se viertes 1 RPS para 1 elementos?

A xulgar polo contexto, estamos a falar da carga de lectura, porque non hai problemas coa escritura: ata mil, ata cen mil e ás veces pódense inserir varios millóns de filas.

As solicitudes de lectura son moi diferentes. Na selección 1, ClickHouse pode realizar unhas decenas de miles de solicitudes por segundo, polo que incluso as solicitudes dunha chave xa precisarán algúns recursos. E tales consultas de puntos serán máis difíciles que nalgunhas bases de datos de clave-valor, porque para cada lectura é necesario ler un bloque de datos por índice. O noso índice non aborda cada rexistro, senón cada intervalo. É dicir, terás que ler todo o intervalo: por defecto son 8192 liñas. E terás que descomprimir o bloque de datos comprimido de 64 KB a 1 MB. Normalmente, estas consultas dirixidas tardan uns milisegundos en completarse. Pero esta é a opción máis sinxela.

Imos probar algunha aritmética sinxela. Se multiplicas uns milisegundos por mil, obtén uns segundos. É coma se fose imposible estar ao día de mil peticións por segundo, pero de feito é posible, porque temos varios núcleos de procesador. Entón, en principio, ClickHouse ás veces pode conter 1000 RPS, pero para solicitudes curtas, específicamente dirixidas.

Se precisa escalar un clúster de ClickHouse polo número de solicitudes simples, recomendo o máis sinxelo: aumentar o número de réplicas e enviar solicitudes a unha réplica aleatoria. Se unha réplica contén cincocentas solicitudes por segundo, o que é completamente realista, entón tres réplicas xestionarán mil e medio.

Ás veces, por suposto, pode configurar ClickHouse para o número máximo de lecturas de puntos. Que se necesita para iso? O primeiro é reducir a granularidade do índice. Neste caso, non debe reducirse a un, senón partindo de que o número de entradas no índice será de varios millóns ou decenas de millóns por servidor. Se a táboa ten cen millóns de filas, a granularidade pódese establecer en 64.

Pode reducir o tamaño do bloque comprimido. Hai configuracións para isto tamaño mínimo do bloque de compresión, tamaño máximo de bloque de compresión. Pódense reducir, recargar con datos e, a continuación, as consultas dirixidas serán máis rápidas. Pero aínda así, ClickHouse non é unha base de datos de clave-valor. Un gran número de solicitudes pequenas é un antipatrón de carga.

Kirill Shvakov: Vou dar consellos por se hai contas ordinarias alí. Esta é unha situación bastante estándar cando ClickHouse almacena algún tipo de contador. Teño un usuario, é de tal país, e algún terceiro campo, e teño que ir incrementando algo. Toma MySQL, fai unha clave única -en MySQL é unha clave duplicada e en PostgreSQL é un conflito- e engade un signo máis. Isto funcionará moito mellor.

Cando non tes moitos datos, non ten moito sentido usar ClickHouse. Hai bases de datos regulares e fano ben.

Que podo modificar en ClickHouse para que haxa máis datos na caché?

Imaxinemos unha situación: os servidores teñen 256 GB de RAM, na rutina diaria ClickHouse leva uns 60-80 GB, no pico, ata 130. O que se pode activar e axustar para que haxa máis datos na caché e, en consecuencia, hai menos viaxes ao disco?

Normalmente, a caché de páxinas do sistema operativo fai un bo traballo. Se só abres a parte superior, miras alí caché ou libre -tamén di canto hai almacenado na caché-, entón notarás que toda a memoria libre se usa para a caché. E ao ler estes datos, leranse non desde o disco, senón desde a memoria RAM. Ao mesmo tempo, podo dicir que a caché úsase de forma eficaz porque son os datos comprimidos os que se almacenan na caché.

Non obstante, se queres acelerar aínda máis algunhas consultas sinxelas, é posible habilitar unha caché nos datos descomprimidos dentro de ClickHouse. Chámase caché sen comprimir. No ficheiro de configuración config.xml, establece o tamaño da caché sen comprimir co valor que necesites. Recomendo non máis da metade da memoria RAM libre, porque o resto pasará debaixo da caché da páxina.

Ademais, hai dúas opcións de nivel de solicitude. Primeira configuración - usar caché sen comprimir - Inclúe o seu uso. Recoméndase activalo para todas as solicitudes, excepto as pesadas, que poden ler todos os datos e limpar a caché. E a segunda configuración é algo así como o número máximo de liñas para usar a caché. Limita automaticamente as consultas grandes para que salten a caché.

Como podo configurar storage_configuration para o almacenamento na RAM?

Na nova documentación de ClickHouse lin a sección relacionada con almacenamento de datos. A descrición contén un exemplo con SSD rápido.

Pregúntome como se pode configurar o mesmo coa memoria quente de volume. E unha pregunta máis. Como funciona select con esta organización de datos, lerá todo o conxunto ou só o que está no disco e estes datos están comprimidos na memoria? E como funciona a sección de prewhere cunha organización de datos deste tipo?

Esta configuración afecta ao almacenamento dos anacos de datos e o seu formato non cambia de ningún xeito.
Vexamos máis de cerca.

Pode configurar o almacenamento de datos na memoria RAM. Todo o que está configurado para o disco é a súa ruta. Crea unha partición tmpfs que está montada nalgún camiño do sistema de ficheiros. Especificas este camiño como camiño para almacenar datos para a partición máis quente, comezan a chegar e escribirse alí os datos, todo está ben.

Pero non recomendo facelo debido á baixa fiabilidade, aínda que se tes polo menos tres réplicas en diferentes centros de datos, é posible. Se ocorre algo, os datos serán restaurados. Imaxinemos que o servidor se apagou de súpeto e volveuse a conectar. A partición volveuse a montar, pero alí non había nada. Cando se inicia o servidor ClickHouse, ve que non ten estas pezas, aínda que, segundo os metadatos de ZooKeeper, deberían estar alí. Mira que réplicas as teñen, pídeas e descárgaas. Deste xeito, os datos serán restaurados.

Neste sentido, almacenar datos na RAM non é fundamentalmente diferente de almacenalos en disco, porque cando os datos se escriben no disco, tamén acaban primeiro na caché da páxina e escríbense fisicamente despois. Isto depende da opción de montaxe do sistema de ficheiros. Pero por se acaso, direi que ClickHouse non fsync ao inserir.

Neste caso, os datos na memoria RAM almacénanse exactamente no mesmo formato que no disco. A consulta de selección do mesmo xeito selecciona as pezas que se deben ler, selecciona os intervalos de datos necesarios nas pezas e lese. E prewhere funciona exactamente igual, independentemente de se os datos estaban na RAM ou no disco.

Ata que número de valores únicos é eficaz a baixa cardinalidade?

A baixa cardinalidade está deseñada intelixentemente. Compila dicionarios de datos, pero son locais. En primeiro lugar, hai diferentes dicionarios para cada peza e, en segundo lugar, mesmo dentro dunha peza poden ser diferentes para cada rango. Cando o número de valores únicos alcanza un número límite -un millón, creo-, o dicionario simplemente é arquivado e créase un novo.

A resposta é en xeral: para cada rango local, por exemplo, para cada día, nalgún lugar é efectivo ata un millón de valores únicos. Despois haberá simplemente un repliegue, no que se empregarán moitos dicionarios diferentes, e non só un. Funcionará aproximadamente igual que unha columna de cadea normal, quizais un pouco menos eficiente, pero non haberá unha degradación grave do rendemento.

Cales son as mellores prácticas para buscar texto completo nunha táboa con cinco mil millóns de filas?

Hai diferentes respostas. O primeiro é dicir que ClickHouse non é un motor de busca de texto completo. Existen sistemas especiais para iso, por exemplo, Elasticsearch и Esfinxe. Non obstante, cada vez vexo máis xente que está a cambiar de Elasticsearch a ClickHouse.

Por que ocorre isto? Explícano polo feito de que Elasticsearch deixa de facer fronte á carga nalgúns volumes, comezando pola construción de índices. Os índices vólvense demasiado engorrosos e, se simplemente transfire os datos a ClickHouse, resulta que se almacenan varias veces de forma máis eficiente en termos de volume. Ao mesmo tempo, as consultas de busca moitas veces non eran tales que fose necesario atopar algunha frase en todo o volume de datos, tendo en conta a morfoloxía, pero outras completamente diferentes. Por exemplo, busque algunha subsecuencia de bytes nos rexistros das últimas horas.

Neste caso, crea un índice en ClickHouse, cuxo primeiro campo será a data e a hora. E o maior corte de datos basearase no intervalo de datas. Dentro do intervalo de datas seleccionado, por regra xeral, xa é posible realizar unha busca de texto completo, mesmo usando o método de forza bruta usando like. O operador like en ClickHouse é o máis eficiente que podes atopar. Se atopas algo mellor, dime.

Pero aínda así, como é unha exploración completa. E a exploración completa pode ser lenta non só na CPU, senón tamén no disco. Se de súpeto tes un terabyte de datos ao día e buscas unha palabra durante o día, terás que escanear o terabyte. E probablemente estea en discos duros habituais e, ao final, cargaranse de tal xeito que non poderás acceder a este servidor a través de SSH.

Neste caso, estou preparado para ofrecer un pequeno truco máis. É experimental: pode funcionar, quizais non. ClickHouse ten índices de texto completo en forma de filtros de trigrama Bloom. Os nosos compañeiros de Arenadata xa probaron estes índices, e moitas veces funcionan exactamente como se pretende.

Para usalos correctamente, debes ter unha boa comprensión de como funcionan exactamente: que é un filtro Bloom trigrama e como elixir o seu tamaño. Podo dicir que axudarán para consultas sobre algunhas frases raras, subcadeas que raramente se atopan nos datos. Neste caso, seleccionaranse subintervalos mediante índices e leranse menos datos.

Recentemente, ClickHouse engadiu funcións aínda máis avanzadas para a busca de texto completo. Trátase, en primeiro lugar, dunha busca dunha serie de subcadeas ao mesmo tempo nunha pasada, incluíndo opcións que distinguen entre maiúsculas e minúsculas, que non distinguen entre maiúsculas e minúsculas, con soporte para UTF-8 ou só para ASCII. Elixe o máis eficaz que necesites.

Tamén apareceu a busca de varias expresións regulares nunha única pasada. Non precisa escribir X como unha subcadea ou X como outra subcadea. Escribes de inmediato, e todo faise o máis eficiente posible.

En terceiro lugar, agora hai unha busca aproximada de expresións regulares e unha busca aproximada de subcadeas. Se alguén escribiu mal unha palabra, buscarase a máxima coincidencia.

Cal é a mellor forma de organizar o acceso a ClickHouse para un gran número de usuarios?

Indícanos a mellor forma de organizar o acceso para un gran número de consumidores e analistas. Como formar unha cola, priorizar o máximo de consultas simultáneas e con que ferramentas?

Se o clúster é o suficientemente grande, entón unha boa solución sería crear dous servidores máis, que se converterán nun punto de entrada para os analistas. É dicir, non permitir que os analistas accedan a fragmentos específicos do clúster, senón que simplemente crean dous servidores baleiros, sen datos, e configuren dereitos de acceso a eles. Neste caso, a configuración do usuario para as solicitudes distribuídas transfírese a servidores remotos. É dicir, configuras todo nestes dous servidores e a configuración ten un efecto sobre todo o clúster.

En principio, estes servidores non teñen datos, pero a cantidade de RAM neles é moi importante para executar solicitudes. O disco tamén se pode usar para datos temporais se está activada a agregación externa ou a clasificación externa.

É importante mirar a configuración que está asociada con todos os límites posibles. Se agora vou ao clúster Yandex.Metrica como analista e fago unha solicitude seleccione o reconto de acertos, entón daraseme inmediatamente unha excepción de que non podo executar a solicitude. O número máximo de filas que se me permite escanear é de cen mil millóns, e en total hai cincuenta billóns delas nunha táboa do clúster. Esta é a primeira limitación.

Digamos que elimine o límite de filas e realizo a consulta de novo. A continuación, verei a seguinte excepción: a configuración activada índice de forza por data. Non podo completar a consulta se non especifiquei un intervalo de datas. Non tes que confiar nos analistas para especificalo manualmente. Un caso típico é cando se escribe un intervalo de datas onde a data do evento entre semana. E entón simplemente especificaron un corchete no lugar equivocado, e no canto de e resultou ser ou - ou coincidencia de URL. Se non hai límite, rastrexará a columna URL e só desperdiciará unha tonelada de recursos.

Ademais, ClickHouse ten dúas opcións de prioridade. Por desgraza, son moi primitivos. Un chámase simplemente prioridade. Se a prioridade ≠ 0 e as solicitudes con certa prioridade se están executando, pero se está a executar unha solicitude cun valor de prioridade inferior a, o que significa unha prioridade máis alta, entón unha solicitude cun valor de prioridade maior, o que significa unha prioridade inferior , simplemente está suspendido e non funcionará en absoluto durante este tempo.

Esta é unha configuración moi bruta e non é adecuada para casos nos que o clúster ten unha carga constante. Pero se tes solicitudes curtas e abundantes que son importantes e o clúster está na súa maioría inactivo, esta configuración é adecuada.

Chámase a seguinte configuración de prioridade Prioridade do fío do sistema operativo. Simplemente establece o valor agradable para todos os fíos de execución de solicitudes para o planificador de Linux. Funciona así, pero segue funcionando. Se estableces o valor mínimo agradable (é o maior en valor e, polo tanto, a prioridade máis baixa) e estableces -19 para solicitudes con prioridade alta, entón a CPU consumirá solicitudes de baixa prioridade unhas catro veces menos que as de alta prioridade.

Tamén cómpre configurar o tempo máximo de execución da solicitude, por exemplo, cinco minutos. A velocidade mínima de execución de consultas é o máis interesante. Esta configuración existe desde hai moito tempo e é necesario non só para afirmar que ClickHouse non ralentiza, senón para forzalo.

Imaxina, configuraches: se algunha consulta procesa menos dun millón de filas por segundo, non podes facelo. Isto deshonra o noso bo nome, a nosa boa base de datos. Prohibemos isto. En realidade, hai dúas opcións. Un chámase velocidade mínima de execución - en liñas por segundo, e o segundo chámase tempo de espera antes de comprobar a velocidade mínima de execución - quince segundos por defecto. É dicir, son posibles quince segundos, e despois, se é lento, só tes que lanzar unha excepción e abortar a solicitude.

Tamén cómpre configurar cotas. ClickHouse ten unha función de cota integrada que conta o consumo de recursos. Pero, por desgraza, non os recursos de hardware como CPU, discos, senón os lóxicos: o número de solicitudes procesadas, liñas e bytes lidos. E pode configurar, por exemplo, un máximo de cen solicitudes en cinco minutos e mil solicitudes por hora.

Por que é importante? Porque algunhas consultas de análise realizaranse manualmente directamente desde o cliente ClickHouse. E todo estará ben. Pero se tes analistas avanzados na túa empresa, escribirán un guión e pode haber un erro no guión. E este erro fará que a solicitude se execute nun bucle infinito. Isto é do que debemos protexernos.

É posible dar os resultados dunha consulta a dez clientes?

Temos varios usuarios aos que lles gusta entrar con solicitudes moi grandes ao mesmo tempo. A solicitude é grande e, en principio, execútase rapidamente, pero debido ao feito de que hai moitas solicitudes deste tipo ao mesmo tempo, faise moi dolorosa. É posible executar a mesma solicitude, que chegou dez veces seguidas, unha vez, e dar o resultado a dez clientes?

O problema é que non temos os resultados da caché ou caché de datos intermedios. Hai unha caché de páxinas do sistema operativo, o que impedirá que volvas ler os datos do disco, pero, desafortunadamente, os datos seguirán descomprimindo, deserializando e reprocesando.

Gustaríame evitar isto dalgún xeito, xa sexa almacenando na caché datos intermedios ou aliñando consultas similares nalgún tipo de cola e engadindo unha caché de resultados. Actualmente temos unha solicitude de extracción en desenvolvemento que engade unha caché de solicitudes, pero só para as subconsultas nas seccións de entrada e unión, é dicir, a solución está incompleta.

Non obstante, tamén nos enfrontamos a tal situación. Un exemplo particularmente canónico son as consultas paxinadas. Hai un informe, ten varias páxinas, e hai unha solicitude de límite 10. Despois o mesmo, pero límite 10,10. Despois outra páxina seguinte. E a pregunta é, por que contamos todo isto cada vez? Pero agora non hai solución, e non hai forma de evitala.

Hai unha solución alternativa que se coloca como sidecar xunto a ClickHouse: ClickHouse Proxy.

Kirill Shvakov: ClickHouse Proxy ten un limitador de velocidade e unha caché de resultados incorporada. Alí fixéronse moitos axustes porque se estaba solucionando un problema similar. O proxy permítelle limitar as solicitudes poñéndoas en cola e configurar canto tempo de vida a caché de solicitudes. Se as solicitudes fosen realmente as mesmas, Proxy enviaraas moitas veces, pero só irá a ClickHouse unha vez.

Nginx tamén ten unha caché na versión gratuíta, e isto tamén funcionará. Nginx incluso ten configuracións que, se as solicitudes chegan ao mesmo tempo, ralentizará outras ata que se complete unha. Pero é en ClickHouse Proxy onde a configuración faise moito mellor. Foi feito especificamente para ClickHouse, concretamente para estas solicitudes, polo que é máis axeitado. Ben, é fácil de instalar.

Que pasa coas operacións asíncronas e as vistas materializadas?

Hai un problema de que as operacións co motor de reprodución son asíncronas: primeiro escríbense os datos e despois colapsan. Se unha tableta materializada con algúns agregados vive baixo o signo, escribiranse duplicados nela. E se non hai unha lóxica complexa, entón os datos duplicaranse. Que podes facer respecto diso?

Hai unha solución obvia: implementar un disparador nunha determinada clase de matviews durante unha operación de colapso asíncrona. Existen solucións ou plans para implementar unha funcionalidade similar?

Paga a pena entender como funciona a deduplicación. O que che digo agora non é relevante para a pregunta, pero por se paga a pena lembralo.

Ao inserir nunha táboa replicada, hai unha deduplicación de todos os bloques inseridos. Se volve inserir o mesmo bloque que contén o mesmo número das mesmas filas na mesma orde, desduplicaranse os datos. Recibirá "Ok" en resposta á inserción, pero de feito escribirase un paquete de datos e non se duplicará.

Isto é necesario para a certeza. Se recibe "Ok" durante a inserción, os seus datos foron inseridos. Se recibes un erro de ClickHouse, significa que non se inseriron e tes que repetir a inserción. Pero se a conexión se rompe durante a inserción, entón non sabe se os datos foron inseridos ou non. A única opción é repetir a inserción de novo. Se realmente se inseriron os datos e os volveu inserir, hai unha deduplicación de bloques. Isto é necesario para evitar duplicados.

E tamén é importante como funciona para as vistas materializadas. Se os datos foron deduplicados cando se inseriron na táboa principal, tampouco pasarán á vista materializada.

Agora sobre a pregunta. A túa situación é máis complicada porque estás gravando duplicados de liñas individuais. É dicir, non se duplica o paquete completo, senón liñas específicas, que colapsan nun segundo plano. De feito, os datos colapsaranse na táboa principal, pero os datos sen contraer pasarán á vista materializada e durante as fusións non ocorrerá nada coas vistas materializadas. Porque unha vista materializada non é máis que un disparador de inserción. Durante outras operacións, non lle ocorre nada adicional.

E aquí non podo facerte feliz. Só tes que buscar unha solución específica para este caso. Por exemplo, é posible reproducilo nunha vista materializada e o método de deduplicación pode funcionar do mesmo xeito. Pero, por desgraza, non sempre. Se está agregando, non funcionará.

Kirill Shvakov: Tamén tivemos construción de muletas no seu día. Houbo un problema de que hai impresións publicitarias e hai algúns datos que podemos mostrar en tempo real: só son impresións. Raramente se duplican, pero se isto ocorre, de todos os xeitos colapsarémolos máis tarde. E había cousas que non se podían duplicar: clics e toda esta historia. Pero tamén quería ensinalos case inmediatamente.

Como se fixeron as vistas materializadas? Había vistas onde se escribiu directamente: escribiuse en datos brutos e en vistas. Alí, nalgún momento os datos non son moi correctos, duplícanse, etc. E hai unha segunda parte da táboa, onde se ven exactamente igual que as vistas materializadas, é dicir, son absolutamente idénticas en estrutura. De cando en vez recalculamos os datos, contamos os datos sen duplicados, escribimos nesas táboas.

Pasamos pola API; isto non funcionará manualmente en ClickHouse. E a API mira: cando teño a data da última incorporación á táboa, onde se garante que xa se calcularon os datos correctos, e fai unha solicitude a unha táboa e a outra. Dunha a solicitude selecciona ata un tempo determinado, e do outro obtén o que aínda non foi calculado. E funciona, pero non só a través de ClickHouse.

Se tes algún tipo de API (para analistas, para usuarios), entón, en principio, esta é unha opción. Sempre estás contando, sempre contando. Isto pódese facer unha vez ao día ou noutro momento. Elixes por ti mesmo un rango que non necesitas e non é crítico.

ClickHouse ten moitos rexistros. Como podo ver todo o que lle pasa ao servidor dunha ollada?

ClickHouse ten un gran número de rexistros diferentes, e este número está aumentando. Nas versións novas, algunhas delas incluso están habilitadas por defecto; nas versións máis antigas deben estar activadas ao actualizar. Porén, cada vez son máis. En definitiva, gustaríame ver o que está a suceder co meu servidor agora, quizais nalgún tipo de panel de resumo.

Tes un equipo de ClickHouse, ou os equipos dos teus amigos, que admitan algunha funcionalidade de paneis de control preparados que mostrarían estes rexistros como un produto acabado? En definitiva, só mirar os rexistros en ClickHouse é xenial. Pero estaría moi chulo que xa estivese preparado en forma de panel. Daríame unha patada.

Hai cadros de mando, aínda que non están estandarizados. Na nosa empresa, uns 60 equipos usan ClickHouse, e o máis estraño é que moitos deles teñen cadros de mando feitos por eles mesmos, e un pouco diferentes. Algúns equipos usan unha instalación interna de Yandex.Cloud. Hai algúns informes xa feitos, aínda que non todos os necesarios. Outros teñen os seus.

Os meus compañeiros de Metrica teñen o seu propio panel en Grafana e eu teño o meu propio para o seu clúster. Estou mirando cousas como caché hit para a caché serif. E aínda máis difícil é que usemos diferentes ferramentas. Creei o meu panel usando unha ferramenta moi antiga chamada Graphite-web. É completamente feo. E sigo usándoo deste xeito, aínda que Grafana probablemente sería máis cómodo e fermoso.

O básico nos cadros de mando é o mesmo. Estas son as métricas do sistema para o clúster: CPU, memoria, disco, rede. Outros: número de solicitudes simultáneas, número de combinacións simultáneas, número de solicitudes por segundo, número máximo de anacos para as particións da táboa MergeTree, atraso de replicación, tamaño da cola de replicación, número de filas inseridas por segundo, número de bloques inseridos por segundo. Isto é todo o que se obtén non de rexistros, senón de métricas.

Vladimir Kolobaev: Alexey, gustaríame corrixilo un pouco. Hai Grafana. Grafana ten unha fonte de datos, que é ClickHouse. É dicir, podo facer solicitudes desde Grafana directamente a ClickHouse. ClickHouse ten unha táboa con rexistros, é o mesmo para todos. Como resultado, quero acceder a esta táboa de rexistro en Grafana e ver as solicitudes que fai o meu servidor. Sería xenial ter un panel coma este.

Eu mesmo paseino en bicicleta. Pero teño unha pregunta: se todo está estandarizado e Grafana é usado por todos, por que Yandex non ten un panel tan oficial?

Kirill Shvakov: De feito, a fonte de datos que vai a ClickHouse agora admite Altinity. E só quero dar un vector de onde cavar e a quen empurrar. Podes preguntarlles, porque Yandex aínda fai ClickHouse, e non a historia que o rodea. Altinity é a principal empresa que actualmente promove ClickHouse. Non o abandonarán, senón que o apoiarán. Porque, en principio, para cargar un panel no sitio web de Grafana só tes que rexistrarte e cargalo, non hai problemas especiais.

Alexey Milovidov: Durante o ano pasado, ClickHouse engadiu moitas capacidades de creación de perfís de consulta. Existen métricas para cada solicitude sobre o uso de recursos. E recentemente, engadimos un perfilador de consultas de nivel inferior para ver onde está gastando unha consulta cada milisegundo. Pero para usar esta funcionalidade, teño que abrir o cliente da consola e escribir unha solicitude, que sempre esquezo. Gardeino nalgún lugar e sigo esquecendo onde exactamente.

Gustaríame que houbese unha ferramenta que acabase de dicir: aquí están as túas consultas pesadas, agrupadas por clase de consulta. Premei nun, e dicíanme que por iso é pesado. Non existe esa solución agora. E é bastante estraño que cando a xente me pregunta: "Dígame, hai algún paneis preparado para Grafana?", eu diga: "Vai ao sitio web de Grafana, hai unha comunidade de "Paneis" e hai un panel. de Dimka, hai un panel de mandos de Kostyan. Non sei o que é, eu non o usei".

Como influír nas fusións para que o servidor non se bloquee en OOM?

Teño unha táboa, só hai unha partición na táboa, é ReplaceingMergeTree. Levo catro anos escribindo datos nel. Necesitaba facer un cambio nel e eliminar algúns datos.

Fixen isto e, durante o procesamento desta solicitude, consumiuse toda a memoria de todos os servidores do clúster e todos os servidores do clúster pasaron a OOM. Despois levantáronse todos xuntos, comezaron a fusionar esta mesma operación, este bloque de datos, e volveron caer en OOM. Entón levantáronse de novo e volveron caer. E isto non parou.

Entón resultou que este era en realidade un erro que os mozos solucionaron. Isto é moi chulo, moitas grazas. Pero quedou un residuo. E agora, cando penso en facer algún tipo de fusión na táboa, teño unha pregunta: por que non podo influír dalgún xeito nestas fusións? Por exemplo, limitalos pola cantidade de RAM necesaria ou, en principio, pola cantidade que procesará esta táboa en particular.

Teño unha táboa chamada "Métricas", por favor, procesámola en dous fíos. Non hai que crear dez ou cinco fusións en paralelo, faino en dúas. Creo que teño memoria suficiente para dous, pero pode que non sexa suficiente para procesar dez. Por que permanece o medo? Porque a táboa medra, e algún día estarei ante unha situación que, en principio, xa non se debe a un erro, senón a que os datos cambiarán en cantidade tan grande que simplemente non terei suficiente memoria no servidor. E entón o servidor fallará en OOM cando se fusione. Ademais, podo cancelar a mutación, pero Merji xa non está.

Xa sabes, ao combinar, o servidor non caerá en OOM, porque ao combinar, a cantidade de RAM só se usa para un pequeno intervalo de datos. Así que todo estará ben independentemente da cantidade de datos.

Vladimir Kolobaev: Ben. Aquí o momento é tal que despois de corrixir o erro, descarguei unha nova versión para min, e noutra táboa, unha máis pequena, onde hai moitas particións, realicei unha operación similar. E durante a fusión, queimáronse preto de 100 GB de RAM no servidor. Tiña 150 ocupados, 100 comidos e unha fiestra de 50 GB, polo que non caín en OOM.

Que me protexe actualmente de caer en OOM se realmente consome 100 GB de RAM? Que facer se de súpeto se esgota a memoria RAM das fusións?

Alexey Milovidov: Hai tal problema que o consumo de RAM específicamente para a fusión non está limitado. E o segundo problema é que se se asignou algún tipo de combinación, entón debe executarse porque está rexistrado no rexistro de replicación. O rexistro de replicación son as accións necesarias para levar a réplica a un estado coherente. Se non realiza manipulacións manuais que farán retroceder este rexistro de replicación, a combinación terá que realizarse dun xeito ou doutro.

Por suposto, non sería superfluo ter unha limitación de RAM que "por se acaso" protexa contra OOM. Non axudará a completar a fusión, comezará de novo, alcanzará algún limiar, lanzará unha excepción e, a continuación, comezará de novo; nada bo sairá disto. Pero, en principio, sería útil introducir esta restrición.

Como se desenvolverá o controlador Golang para ClickHouse?

O controlador de Golang, que foi escrito por Kirill Shvakov, agora conta co apoio oficial do equipo de ClickHouse. El no repositorio ClickHouse, agora é grande e real.

Unha pequena nota. Hai un marabilloso e amado repositorio de formas normais de orde infinita: este é Vertica. Tamén teñen o seu propio controlador oficial de Python, que é compatible cos desenvolvedores de Vertica. E varias veces ocorreu que as versións de almacenamento e as versións do controlador diverxían de forma bastante dramática, e o controlador nalgún momento deixou de funcionar. E o segundo punto. O soporte para este controlador oficial, paréceme, realízase polo sistema "pezón": escribes un problema e pende para sempre.

Teño dúas preguntas. Agora o controlador Golang de Kirill é case a forma predeterminada de comunicarse desde Golang con ClickHouse. A menos que alguén aínda se comunique a través da interface http porque lle gusta así. Como será o desenvolvemento deste motor? Será sincronizado con calquera cambio de ruptura no propio repositorio? E cal é o procedemento para considerar unha cuestión?

Kirill Shvakov: O primeiro é como se organiza todo burocráticamente. Este punto non foi discutido, polo que non teño nada que responder.

Para responder á pregunta sobre o problema, necesitamos un pouco de historial do condutor. Traballei nunha empresa que tiña moitos datos. Era un spinner publicitario cunha gran cantidade de eventos que debían gardar nalgún lugar. E nalgún momento apareceu ClickHouse. Encheuno de datos, e ao principio todo estaba ben, pero despois o ClickHouse fallou. Nese momento decidimos que non o necesitabamos.

Un ano despois, volvemos á idea de usar ClickHouse e necesitabamos escribir datos alí dalgún xeito. A mensaxe introductoria foi esta: o hardware é moi débil, hai poucos recursos. Pero sempre traballamos deste xeito, e por iso miramos cara ao protocolo nativo.

Como estabamos traballando en Go, estaba claro que necesitabamos un condutor de Go. Fíxeno case a tempo completo: era a miña tarefa laboral. Levámolo a un certo punto e, en principio, ninguén asumiu que o usaría ninguén máis que nós. Entón CloudFlare veu exactamente o mesmo problema, e durante algún tempo traballamos con eles moi ben, porque tiñan as mesmas tarefas. Ademais, fixemos isto tanto en ClickHouse como no controlador.

Nalgún momento, simplemente deixei de facelo, porque a miña actividade en canto a ClickHouse e traballo cambiou un pouco. Polo tanto, os asuntos non están pechados. Periódicamente, as persoas que precisan algo comprométense co repositorio. Despois miro a solicitude de extracción e ás veces ata edito algo eu, pero isto ocorre raramente.

Quero volver ao condutor. Hai varios anos, cando comezou todo isto, ClickHouse tamén era diferente e con capacidades diferentes. Agora entendemos como refacer o controlador para que funcione ben. Se isto ocorre, a versión 2 será incompatible en calquera caso debido ás muletas acumuladas.

Non sei como organizar este asunto. Eu mesmo non teño moito tempo. Se algunhas persoas rematan o condutor, podo axudarlles e dicirlles que facer. Pero a participación activa de Yandex no desenvolvemento do proxecto aínda non foi discutida.

Alexey Milovidov: De feito, aínda non hai burocracia sobre estes condutores. O único é que se envían a unha organización oficial, é dicir, este controlador está recoñecido como a solución oficial predeterminada para Go. Hai outros controladores, pero veñen por separado.

Non temos ningún desenvolvemento interno para estes controladores. A cuestión é se podemos contratar unha persoa individual, non para este condutor en particular, senón para o desenvolvemento de todos os condutores da comunidade, ou podemos atopar alguén de fóra.

O dicionario externo non se carga despois dun reinicio coa configuración lazy_load activada. Que facer?

Temos a configuración lazy_load activada e, despois de reiniciar o servidor, o dicionario non se carga por si só. Solamente aparece despois de que o usuario accede a este dicionario. E a primeira vez que accedo a el, dá un erro. É posible cargar automaticamente dicionarios dalgún xeito usando ClickHouse, ou é necesario controlar sempre a súa preparación para que os usuarios non reciban erros?

Quizais teñamos unha versión antiga de ClickHouse, polo que o dicionario non se cargou automaticamente. Podería ser este o caso?

En primeiro lugar, pódese forzar a carga dos dicionarios mediante unha consulta Recarga de dicionarios do sistema. En segundo lugar, no que respecta ao erro: se o dicionario xa está cargado, as consultas funcionarán en función dos datos que se cargaron. Se o dicionario aínda non foi cargado, cargarase directamente durante a solicitude.

Isto non é moi conveniente para dicionarios pesados. Por exemplo, necesitas sacar un millón de filas de MySQL. Alguén fai unha selección sinxela, pero esta selección agardará polo mesmo millón de filas. Aquí hai dúas solucións. O primeiro é desactivar lazy_load. En segundo lugar, cando o servidor estea activado, antes de poñerlle a carga, faino dicionario de recarga do sistema ou simplemente facer unha consulta que use un dicionario. Despois cargarase o dicionario. Debes controlar a dispoñibilidade dos dicionarios coa configuración lazy_load activada, porque ClickHouse non os carga automaticamente.

A resposta á última pregunta é que a versión é antiga ou que debe ser depurada.

Que facer co feito de que o sistema recarga os dicionarios non carga ningún dos moitos dicionarios se polo menos un deles falla cun erro?

Hai outra pregunta sobre os dicionarios de recarga do sistema. Temos dous dicionarios: un non está cargado, o segundo está cargado. Neste caso, os dicionarios de recarga do sistema non cargan ningún dicionario e tes que cargar punto por punto un específico polo seu nome usando o dicionario de recarga do sistema. Tamén está relacionado coa versión ClickHouse?

Quero facerte feliz. Este comportamento estaba cambiando. Isto significa que se actualizas ClickHouse, tamén cambiará. Se non está satisfeito co seu comportamento actual Recarga de dicionarios do sistema, actualiza e esperemos que cambie para mellor.

Hai algunha forma de configurar os detalles na configuración de ClickHouse, pero non mostralos en caso de erros?

A seguinte pregunta é sobre erros relacionados co dicionario, é dicir, detalles. Especificamos os detalles da conexión na configuración de ClickHouse para o dicionario e, se hai un erro, recibimos estes detalles e contrasinal como resposta.

Resolvemos este erro engadindo detalles á configuración do controlador ODBC. Hai algunha forma de configurar os detalles na configuración de ClickHouse, pero non mostrar estes detalles en caso de erros?

A verdadeira solución aquí é especificar estas credenciais en odbc.ini e no propio ClickHouse especificar só o nome da fonte de datos ODBC. Isto non ocorrerá para outras fontes de dicionarios - nin para o dicionario con MySQL nin para os demais, non deberías ver o contrasinal cando recibas unha mensaxe de erro. Para ODBC, tamén buscarei: se existe, só tes que eliminalo.

Bonificación: fondos para Zoom de reunións

Ao facer clic na imaxe, abriranse fondos extra das reunións para os lectores máis persistentes. Apagamos o lume xunto coas mascotas tecnolóxicas de Avito, conversamos con compañeiros da sala do administrador do sistema ou do club de informática da vella escola e realizamos reunións diarias baixo a ponte co pano de graffiti.

ClickHouse para usuarios avanzados en preguntas e respostas

Fonte: www.habr.com

Engadir un comentario