ClickHouse per utenti esperti in domande e risposte

Ad aprile, gli ingegneri di Avito si sono riuniti per incontri online con il principale sviluppatore di ClickHouse Alexey Milovidov e Kirill Shvakov, uno sviluppatore Golang di Integros. Abbiamo discusso di come utilizziamo un sistema di gestione di database e quali difficoltà incontriamo.

Sulla base dell'incontro, abbiamo compilato un articolo con le risposte degli esperti alle domande nostre e del pubblico su backup, resharding dei dati, dizionari esterni, driver Golang e aggiornamento delle versioni di ClickHouse. Potrebbe essere utile agli sviluppatori che stanno già lavorando attivamente con il DBMS Yandex e sono interessati al suo presente e futuro. Per impostazione predefinita, le risposte sono di Alexey Milovidov, se non diversamente scritto.

Fai attenzione, c'è molto testo sotto il taglio. Ci auguriamo che il contenuto con le domande ti aiuti a navigare.

ClickHouse per utenti esperti in domande e risposte

contenuto

Se non vuoi leggere il testo puoi guardare la registrazione degli incontri sul nostro canale YouTube. I codici temporali sono nel primo commento sotto il video.

ClickHouse è costantemente aggiornato, ma i nostri dati no. Cosa fare al riguardo?

ClickHouse è costantemente aggiornato e i nostri dati, che sono stati ottimizzati nell'elaborazione finale, non vengono aggiornati e si trovano in una copia di backup.

Diciamo che abbiamo avuto qualche problema e i dati sono andati persi. Abbiamo deciso di ripristinare e si è scoperto che le vecchie partizioni, archiviate sui server di backup, sono molto diverse dalla versione attualmente utilizzata di ClickHouse. Cosa fare in una situazione del genere ed è possibile?

Una situazione in cui hai ripristinato i dati da un backup in un vecchio formato, ma non si connette alla nuova versione, è impossibile. Ci assicuriamo che il formato dei dati in ClickHouse rimanga sempre compatibile con le versioni precedenti. Questo è molto più importante della compatibilità con le funzionalità precedenti se il comportamento di alcune funzioni utilizzate raramente è cambiato. La nuova versione di ClickHouse dovrebbe sempre essere in grado di leggere i dati archiviati sul disco. Questa è la legge.

Quali sono le migliori pratiche attuali per il backup dei dati da ClickHouse?

Come eseguire i backup, tenendo conto del fatto che disponiamo di un'ottimizzazione delle operazioni finali, di un enorme database di terabyte e di dati aggiornati, diciamo, negli ultimi tre giorni, e quindi non viene eseguita alcuna procedura?

Possiamo creare la nostra soluzione e scrivere sulla bash: raccogliere queste copie di backup in questo e quel modo. Forse non c'è bisogno di stampelle e la bicicletta è stata inventata molto tempo fa?

Cominciamo con le migliori pratiche. I miei colleghi consigliano sempre, in risposta alle domande sui backup, di ricordare loro il servizio Yandex.Cloud, dove questo problema è già stato risolto. Quindi usalo se possibile.

Non esiste una soluzione completa per i backup, integrata al cento per cento in ClickHouse. Ci sono alcuni spazi vuoti che possono essere utilizzati. Per ottenere una soluzione completa, dovrai armeggiare un po' manualmente o creare wrapper sotto forma di script.

Inizierò con le soluzioni più semplici e finirò con quelle più sofisticate, a seconda del volume di dati e della dimensione del cluster. Più grande è il cluster, più complessa diventa la soluzione.

Se la tabella con i dati occupa solo pochi gigabyte, il backup può essere eseguito in questo modo:

  1. Salva la definizione della tabella, ovvero i metadati − mostra crea tabella.
  2. Crea un dump utilizzando il client ClickHouse - select * dal tavolo archiviare. Per impostazione predefinita riceverai un file in formato TabSeparated. Se vuoi essere più efficiente, puoi farlo in formato nativo.

Se la quantità di dati è maggiore, il backup richiederà più tempo e molto spazio. Questo è chiamato backup logico e non è legato al formato dati ClickHouse. Se lo è, come ultima risorsa puoi eseguire un backup e caricarlo su MySQL per il ripristino.

Per i casi più avanzati, ClickHouse ha la capacità integrata di creare un'istantanea delle partizioni nel file system locale. Questa funzionalità è disponibile come richiesta alterare la partizione di congelamento della tabella. O semplicemente alterare il congelamento della tabella - questa è un'istantanea dell'intera tabella.

Lo snapshot verrà creato in modo coerente per una tabella su uno shard, ovvero è impossibile creare uno snapshot coerente dell'intero cluster in questo modo. Ma per la maggior parte delle attività non esiste tale necessità ed è sufficiente eseguire una richiesta su ciascun frammento e ottenere uno snapshot coerente. Viene creato sotto forma di collegamenti fisici e pertanto non occupa spazio aggiuntivo. Successivamente, copi questo snapshot sul server di backup o sullo spazio di archiviazione utilizzato per i backup.

Ripristinare un backup di questo tipo è abbastanza semplice. Innanzitutto, crea tabelle utilizzando le definizioni di tabella esistenti. Successivamente, copia gli snapshot salvati delle partizioni in Directory-Detached per queste tabelle ed esegui la query allegare partizione. Questa soluzione è abbastanza adatta per i volumi di dati più grandi.

A volte hai bisogno di qualcosa di ancora più interessante, nei casi in cui hai decine o addirittura centinaia di terabyte su ciascun server e centinaia di server. C'è una soluzione qui che ho preso dai miei colleghi di Yandex.Metrica. Non lo consiglierei a tutti: leggetelo e decidete voi stessi se è adatto o meno.

Per prima cosa devi creare diversi server con scaffali per dischi di grandi dimensioni. Successivamente, su questi server, crea diversi server ClickHouse e configurali in modo che funzionino come un'altra replica per gli stessi frammenti. E quindi utilizza un file system o uno strumento su questi server che ti consenta di creare istantanee. Ci sono due opzioni qui. La prima opzione sono gli snapshot LVM, la seconda opzione è ZFS su Linux.

Dopodiché, ogni giorno devi creare un'istantanea, mentirà e occuperà spazio. Naturalmente, se i dati cambiano, la quantità di spazio aumenterà nel tempo. Questa istantanea può essere eliminata in qualsiasi momento e i dati ripristinati, una soluzione davvero strana. Inoltre, dobbiamo anche limitare queste repliche nella configurazione in modo che non cerchino di diventare leader.

Sarà possibile organizzare un ritardo controllato delle repliche nei pozzi?

Quest'anno hai intenzione di realizzare alberi in ClickHouse. Sarà possibile organizzare un ritardo controllato di repliche al loro interno? Vorremmo usarlo per proteggerci da scenari negativi con alter ego e altri cambiamenti.

È possibile eseguire una sorta di rollback per gli alter? Ad esempio, in un albero esistente, prendi e dì che fino a questo momento applichi le modifiche e da questo momento smetti di applicare le modifiche?

Se un comando è arrivato al nostro cluster e lo ha interrotto, allora abbiamo una replica condizionale con un ritardo di un'ora, dove possiamo dire che usiamolo al momento, ma non applicheremo le modifiche negli ultimi dieci minuti?

Innanzitutto, sul ritardo controllato delle repliche. C'era una richiesta del genere da parte degli utenti e abbiamo creato un problema su Github con la richiesta: "Se qualcuno ne ha bisogno, metti mi piace, metti un cuore". Nessuno ha consegnato e la questione è stata chiusa. Tuttavia, puoi già ottenere questa opportunità configurando ClickHouse. È vero, solo a partire dalla versione 20.3.

ClickHouse esegue costantemente l'unione dei dati in background. Quando un'unione viene completata, un determinato insieme di dati viene sostituito con un pezzo più grande. Allo stesso tempo, i dati che erano lì prima continuano a rimanere sul disco per qualche tempo.

Innanzitutto, continuano a essere archiviati finché esistono query selezionate che li utilizzano, al fine di fornire operazioni non bloccanti. Le query selezionate possono essere facilmente lette dai vecchi blocchi.

In secondo luogo, esiste anche una soglia temporale: i vecchi dati rimangono sul disco per otto minuti. Questi otto minuti possono essere personalizzati e persino trasformati in un giorno. Ciò costerà spazio su disco: a seconda del flusso di dati, risulta che nell'ultimo giorno i dati non solo raddoppieranno, ma potrebbero diventare cinque volte di più. Ma se c'è un problema serio, puoi fermare il server ClickHouse e sistemare tutto.

Ora sorge la domanda su come questo protegga dagli alter ego. Vale la pena dare uno sguardo più approfondito qui, perché nelle versioni precedenti di ClickHouse, l'alter funzionava in modo tale da cambiare direttamente i pezzi. C'è un dato con alcuni file e facciamo, ad esempio, alterare la colonna di rilascio. Quindi questa colonna viene rimossa fisicamente da tutti i blocchi.

Ma a partire dalla versione 20.3, il meccanismo di alterazione è stato completamente modificato e ora i dati sono sempre immutabili. Non cambiano affatto: le modifiche ora funzionano più o meno allo stesso modo delle fusioni. Invece di sostituire un pezzo sul posto, ne creiamo uno nuovo. Nel nuovo blocco, i file che non sono cambiati diventano collegamenti fisici e, se eliminiamo una colonna, semplicemente mancherà nel nuovo blocco. Il vecchio pezzo verrà eliminato per impostazione predefinita dopo otto minuti e qui puoi modificare le impostazioni sopra menzionate.

Lo stesso vale per gli alter ego come le mutazioni. Quando lo fai alterare eliminare o alterare l'aggiornamento, non cambia il pezzo, ma ne crea uno nuovo. E poi cancella quello vecchio.

Cosa succede se la struttura della tabella è cambiata?

Come ripristinare un backup effettuato con il vecchio schema? E la seconda domanda riguarda il caso delle istantanee e degli strumenti del file system. Btrfs va bene qui invece di ZFS su Linux LVM?

Se fate allegare partizione partizioni con una struttura diversa, ClickHouse ti dirà che ciò non è possibile. Questa è la soluzione. Il primo è creare una tabella temporanea del tipo MergeTree con la vecchia struttura, allegare i dati utilizzando attach ed effettuare una query di modifica. Quindi puoi copiare o trasferire questi dati e allegarli nuovamente oppure utilizzare una richiesta alterare la partizione di spostamento della tabella.

Ora la seconda domanda è se è possibile utilizzare Btrfs. Per cominciare, se hai LVM, allora gli snapshot LVM sono sufficienti e il file system può essere ext4, non importa. Con Btrts tutto dipende dalla tua esperienza nell'usarlo. Si tratta di un file system maturo, ma ci sono ancora alcuni sospetti su come tutto funzionerà nella pratica in un particolare scenario. Non consiglierei di usarlo a meno che tu non abbia Btrfs in produzione.

Quali sono le migliori pratiche attuali nel resharding dei dati?

La questione del resharding è complessa e sfaccettata. Ci sono diverse risposte possibili qui. Puoi andare da un lato e dire questo: ClickHouse non ha una funzione di resharding incorporata. Ma temo che questa risposta non vada bene a nessuno. Pertanto, puoi andare dall'altra parte e dire che ClickHouse ha molti modi per riconfigurare i dati.

Se il cluster esaurisce lo spazio o non è in grado di gestire il carico, aggiungi nuovi server. Ma questi server sono vuoti per impostazione predefinita, non ci sono dati su di essi, non c'è carico. È necessario riorganizzare i dati in modo che vengano distribuiti uniformemente nel nuovo cluster più grande.

Il primo modo per farlo è copiare parte delle partizioni su nuovi server utilizzando una richiesta alterare la partizione di recupero della tabella. Ad esempio, hai partizioni per mese e prendi il primo mese del 2017 e lo copi su un nuovo server, quindi copi il terzo mese su un altro nuovo server. E lo fai finché non diventa più o meno uniforme.

Il trasferimento può essere effettuato solo per quelle partizioni che non cambiano durante la registrazione. Per le nuove partizioni, la registrazione dovrà essere disabilitata, poiché il loro trasferimento non è atomico. Altrimenti, ti ritroverai con duplicati o lacune nei dati. Tuttavia, questo metodo è pratico e funziona in modo abbastanza efficace. Le partizioni compresse già pronte vengono trasmesse sulla rete, ovvero i dati non vengono compressi o ricodificati.

Questo metodo ha uno svantaggio e dipende dallo schema di sharding, dal fatto che tu abbia aderito a questo schema di sharding e dalla chiave di sharding che avevi. Nel tuo esempio per il caso delle metriche, la chiave di partizionamento orizzontale è l'hash del percorso. Quando selezioni una tabella distribuita, questa va a tutti gli shard nel cluster contemporaneamente e prende i dati da lì.

Ciò significa che in realtà non ti importa quali dati siano finiti su quale shard. La cosa principale è che i dati lungo un percorso finiscono su uno shard, ma quale non è importante. In questo caso, il trasferimento di partizioni già pronte è perfetto, perché con le query selezionate riceverai anche i dati completi - sia prima che dopo il resharding, lo schema non ha molta importanza.

Ma ci sono casi più complessi. Se a livello di logica dell'applicazione ti affidi a uno schema di sharding speciale, questo client si trova su questo o quel frammento e la richiesta può essere inviata direttamente lì e non alla tabella distribuita. Oppure stai utilizzando una versione abbastanza recente di ClickHouse e hai abilitato l'impostazione ottimizzare il salto dei frammenti inutilizzati. In questo caso, durante la query di selezione, verrà analizzata l'espressione nella sezione where e verrà calcolato quali shard devono essere utilizzati secondo lo schema di sharding. Funziona a condizione che i dati siano partizionati esattamente secondo questo schema di partizionamento orizzontale. Se li hai riorganizzati manualmente, la corrispondenza potrebbe cambiare.

Quindi questo è il metodo numero uno. E sto aspettando la tua risposta, se il metodo è adatto o andiamo avanti.

Vladimir Kolobaev, amministratore di sistema capo di Avito: Alexey, il metodo che hai menzionato non funziona molto bene quando devi distribuire il carico, inclusa la lettura. Possiamo prendere una partizione mensile e possiamo portare il mese precedente su un altro nodo, ma quando arriva una richiesta per questi dati, li caricheremo solo. Ma vorremmo caricare l'intero cluster, perché altrimenti per qualche tempo l'intero carico di lettura verrà elaborato da due shard.

Aleksej Milovidov: La risposta qui è strana: sì, è brutta, ma potrebbe funzionare. Spiegherò esattamente come. Vale la pena esaminare lo scenario di carico che segue i tuoi dati. Se si tratta di monitorare i dati, allora possiamo quasi certamente dire che la stragrande maggioranza delle richieste riguarda dati nuovi.

Hai installato nuovi server, migrato vecchie partizioni, ma hai anche cambiato il modo in cui vengono registrati i nuovi dati. E nuovi dati verranno diffusi in tutto il cluster. Pertanto, dopo soli cinque minuti, le richieste degli ultimi cinque minuti caricheranno uniformemente il cluster; dopo un giorno, le richieste per XNUMX ore caricheranno uniformemente il cluster. E le richieste del mese precedente, purtroppo, andranno solo a una parte dei server del cluster.

Ma spesso non avrai richieste specifiche per febbraio 2019. Molto probabilmente, se le richieste arrivano nel 2019, saranno per l'intero 2019, per un ampio periodo di tempo e non per un intervallo ristretto. E tali richieste potranno anche caricare il cluster in modo uniforme. Ma in generale, la tua osservazione è assolutamente corretta secondo cui si tratta di una soluzione ad hoc che non distribuisce i dati in modo completamente uniforme.

Ho ancora qualche punto per rispondere alla domanda. Uno di questi riguarda come progettare inizialmente uno schema di sharding in modo che il re-sharding causi meno problemi. Questo non è sempre possibile.

Ad esempio, hai dati di monitoraggio. I dati di monitoraggio crescono per tre ragioni. Il primo è l’accumulo di dati storici. Il secondo è la crescita del traffico. E il terzo è l’aumento del numero di cose soggette a monitoraggio. Esistono nuovi microservizi e metriche che devono essere salvati.

È possibile che tra questi l'aumento maggiore sia legato al terzo motivo: l'aumento dell'uso del monitoraggio. E in questo caso vale la pena considerare la natura del carico, quali sono le principali query di selezione. Le query di selezione di base saranno molto probabilmente basate su alcuni sottoinsiemi di metriche.

Ad esempio, l'utilizzo della CPU su alcuni server da parte di alcuni servizi. Si scopre che esiste un certo sottoinsieme di chiavi con cui si ottengono questi dati. E la richiesta stessa di questi dati è molto probabilmente abbastanza semplice e viene completata in decine di millisecondi. Utilizzato per monitorare servizi e dashboard. Spero di averlo capito correttamente.

Vladimir Kolobaev: Il fatto è che molto spesso facciamo appello ai dati storici, poiché confrontiamo la situazione attuale con quella storica in tempo reale. Ed è importante per noi avere un rapido accesso a una grande quantità di dati e ClickHouse fa un ottimo lavoro in questo senso.

Hai assolutamente ragione, riscontriamo la maggior parte delle richieste di lettura nell'ultimo giorno, come qualsiasi sistema di monitoraggio. Ma allo stesso tempo, anche il carico sui dati storici è piuttosto elevato. Si tratta fondamentalmente di un sistema di allerta che gira ogni trenta secondi e dice a ClickHouse: “Dammi i dati delle ultime sei settimane. Ora costruiscimi una sorta di media mobile e confrontiamo il valore attuale con quello storico”.

Vorrei dire che per richieste così recenti abbiamo un'altra piccola tabella in cui memorizziamo solo due giorni di dati, e in essa volano le richieste principali. Inviamo solo query storiche di grandi dimensioni alla tabella partizionata di grandi dimensioni.

Aleksej Milovidov: Sfortunatamente, risulta essere scarsamente applicabile al tuo scenario, ma ti dirò una descrizione di due schemi di sharding cattivi e complessi che non hanno bisogno di essere utilizzati, ma che vengono utilizzati al servizio dei miei amici.

Esiste un cluster principale con eventi Yandex.Metrica. Gli eventi sono visualizzazioni di pagina, clic e conversioni. La maggior parte delle richieste vanno a un sito Web specifico. Apri il servizio Yandex.Metrica, hai un sito web - avito.ru, vai al rapporto e viene effettuata una richiesta per il tuo sito web.

Ma ci sono altre richieste – analitiche e globali – che vengono avanzate dagli analisti interni. Per ogni evenienza, noto che gli analisti interni effettuano richieste solo per i servizi Yandex. Tuttavia, anche i servizi Yandex occupano una quota significativa di tutti i dati. Si tratta di richieste non per contatori specifici, ma per un filtraggio più ampio.

Come organizzare i dati in modo tale che tutto funzioni in modo efficiente per un contatore e anche per le query globali? Un'altra difficoltà è che il numero di richieste in ClickHouse per il cluster Metrics è di diverse migliaia al secondo. Allo stesso tempo, un server ClickHouse non può gestire richieste non banali, ad esempio diverse migliaia al secondo.

La dimensione del cluster è di circa seicento server. Se semplicemente inserisci una tabella distribuita su questo cluster e invii diverse migliaia di richieste lì, diventerà ancora peggio che inviarle a un server. D'altra parte, l'opzione di distribuire i dati in modo uniforme e di richiederli a tutti i server viene immediatamente scartata.

C'è un'opzione diametralmente opposta. Immagina se suddividiamo i dati tra siti e una richiesta per un sito va a uno shard. Ora il cluster sarà in grado di gestire diecimila richieste al secondo, ma su uno shard qualsiasi richiesta funzionerà troppo lentamente. Non sarà più scalabile in termini di throughput. Soprattutto se questo è il sito avito.ru. Non rivelerò il segreto se dico che Avito è uno dei siti più visitati di RuNet. Ed elaborarlo su un frammento sarebbe una follia.

Pertanto, lo schema di sharding è progettato in modo più astuto. L'intero cluster è diviso in una serie di cluster, che chiamiamo livelli. Ogni cluster contiene da una dozzina a diverse dozzine di frammenti. Ci sono trentanove cluster di questo tipo in totale.

Come si ridimensiona tutto questo? Il numero dei cluster non cambia: alcuni anni fa erano trentanove e rimangono tali. Ma all’interno di ciascuno di essi, aumentiamo gradualmente il numero di frammenti man mano che accumuliamo dati. E lo schema di sharding nel suo insieme è così: questi cluster sono divisi in siti Web e per capire quale sito Web si trova su quale cluster, viene utilizzata una metabase separata in MySQL. Un sito - su un cluster. E al suo interno, lo sharding avviene in base agli ID dei visitatori.

Durante la registrazione, li dividiamo per il resto della divisione dell'ID del visitatore. Ma quando si aggiunge un nuovo frammento, lo schema di partizionamento cambia; continuiamo a dividere, ma con il resto della divisione per un altro numero. Ciò significa che un visitatore si trova già su più server e non puoi fare affidamento su questo. Questo viene fatto esclusivamente per garantire che i dati siano compressi meglio. E quando effettuiamo richieste, andiamo alla tabella Distribuita, che esamina il cluster e accede a dozzine di server. Questo è uno schema così stupido.

Ma la mia storia sarebbe incompleta se non dicessi che abbiamo abbandonato questo schema. Nel nuovo schema, abbiamo cambiato tutto e copiato tutti i dati utilizzando clickhouse-copier.

Nel nuovo schema, tutti i siti sono divisi in due categorie: grandi e piccoli. Non so come sia stata scelta la soglia, ma il risultato è che i siti di grandi dimensioni vengono registrati su un cluster, dove ci sono 120 frammenti con tre repliche ciascuno, ovvero 360 server. E lo schema di sharding è tale che qualsiasi richiesta viene inviata a tutti gli shard contemporaneamente. Se ora apri una pagina di report per avito.ru in Yandex.Metrica, la richiesta verrà inviata a 120 server. Ci sono pochi siti di grandi dimensioni in RuNet. E le richieste non sono mille al secondo, ma nemmeno meno di cento. Tutto questo viene tranquillamente masticato dalla tabella Distribuita, che ciascuna di esse elabora con 120 server.

E il secondo cluster riguarda i siti di piccole dimensioni. Di seguito è riportato uno schema di sharding basato sull'ID del sito e ogni richiesta va esattamente a uno shard.

ClickHouse dispone di un'utilità di copiatura di clickhouse. Puoi parlarci di lei?

Dirò subito che questa soluzione è più macchinosa e un po’ meno produttiva. Il vantaggio è che confonde completamente i dati secondo il modello specificato. Ma lo svantaggio dell'utilità è che non viene ripristinato affatto. Copia i dati da uno schema di cluster a un altro schema di cluster.

Ciò significa che affinché funzioni è necessario disporre di due cluster. Possono trovarsi sugli stessi server, ma i dati non verranno comunque spostati in modo incrementale, ma verranno copiati.

Ad esempio, c'erano quattro server, ora ce ne sono otto. Crei una nuova tabella distribuita su tutti i server, nuove tabelle locali e avvii clickhouse-copier, indicando in essa lo schema di lavoro che dovrebbe leggere da lì, accetta il nuovo schema di sharding e trasferisci i dati lì. E sui vecchi server avrai bisogno di una volta e mezza più spazio di quello che c'è adesso, perché i vecchi dati devono rimanere su di essi e la metà degli stessi vecchi dati arriverà su di essi. Se hai pensato in anticipo che i dati devono essere ricondivisi e c'è spazio, allora questo metodo è adatto.

Come funziona Clickhouse-Copier all'interno? Suddivide tutto il lavoro in una serie di attività per l'elaborazione di una partizione di una tabella su un frammento. Tutte queste attività possono essere eseguite in parallelo e clickhouse-copier può essere eseguito su macchine diverse in più istanze, ma ciò che fa per una partizione non è altro che una selezione di inserimento. I dati vengono letti, decompressi, ripartizionati, quindi nuovamente compressi, scritti da qualche parte e riordinati. Questa è una decisione più difficile.

Avevi una cosa pilota chiamata resharding. E con lei?

Nel 2017 avevi una cosa pilota chiamata resharding. C'è anche un'opzione in ClickHouse. A quanto ho capito, non è decollato. Potete dirmi perché è successo questo? Sembra essere molto rilevante.

Il problema è che se è necessario riorganizzare i dati sul posto, è necessaria una sincronizzazione molto complessa per farlo in modo atomico. Quando abbiamo iniziato a esaminare come funziona questa sincronizzazione, è diventato chiaro che c'erano problemi fondamentali. E questi problemi fondamentali non sono solo teorici, ma hanno subito cominciato a manifestarsi nella pratica sotto forma di qualcosa che può essere spiegato in modo molto semplice: niente funziona.

È possibile unire insieme tutti i dati prima di spostarli su dischi lenti?

Domanda su TTL con l'opzione di spostamento su disco lento nel contesto delle fusioni. Esiste un modo, oltre a cron, per unire tutte le parti in una prima di spostarle su dischi lenti?

La risposta alla domanda è se in qualche modo è possibile incollare automaticamente tutti i pezzi in uno prima di trasferirli - no. Non penso che sia necessario. Non è necessario unire tutte le parti in una sola, ma contare semplicemente sul fatto che verranno trasferite automaticamente su dischi lenti.

Abbiamo due criteri per le regole di trasferimento. Il primo è man mano che viene riempito. Se il livello di archiviazione corrente ha meno di una determinata percentuale di spazio libero, selezioniamo un blocco e lo spostiamo nello spazio di archiviazione più lento. O meglio, non più lento, ma successivo, come lo configuri.

Il secondo criterio è la dimensione. Si tratta di spostare pezzi di grandi dimensioni. È possibile regolare la soglia in base allo spazio libero sul disco veloce e i dati verranno trasferiti automaticamente.

Come migrare alle nuove versioni di ClickHouse se non c'è modo di verificare in anticipo la compatibilità?

Questo argomento viene discusso regolarmente nella chat di Telegram di ClickHouse tenendo conto delle diverse versioni, e ancora. Quanto è sicuro eseguire l'aggiornamento dalla versione 19.11 alla 19.16 e, ad esempio, dalla versione 19.16 alla 20.3. Qual è il modo migliore per migrare alle nuove versioni senza poter verificare preventivamente la compatibilità nella sandbox?

Ci sono diverse regole “d’oro” qui. Primo - leggi il registro delle modifiche. È ampio, ma ci sono paragrafi separati sulle modifiche incompatibili con le versioni precedenti. Non trattare questi punti come una bandiera rossa. Di solito si tratta di incompatibilità minori che coinvolgono alcune funzionalità edge che molto probabilmente non utilizzi.

In secondo luogo, se non è possibile verificare la compatibilità nella sandbox e si desidera aggiornare immediatamente in produzione, si consiglia di non farlo. Per prima cosa crea un sandbox e prova. Se non è presente un ambiente di test, molto probabilmente non hai un'azienda molto grande, il che significa che puoi copiare alcuni dati sul tuo laptop e assicurarti che tutto funzioni correttamente su di esso. Puoi anche creare diverse repliche localmente sul tuo computer. Oppure puoi prendere una nuova versione da qualche parte nelle vicinanze e caricare lì alcuni dati, ovvero creare un ambiente di test improvvisato.

Un'altra regola è non aggiornare per una settimana dopo il rilascio della versione a causa del rilevamento di bug in produzione e conseguenti soluzioni rapide. Scopriamo la numerazione delle versioni ClickHouse per non confonderci.

Esiste la versione 20.3.4. Il numero 20 indica l'anno di produzione - 2020. Dal punto di vista di ciò che c'è dentro, questo non ha importanza, quindi non gli presteremo attenzione. Avanti - 20.3. Aumentiamo il secondo numero - in questo caso 3 - ogni volta che rilasciamo una versione con qualche nuova funzionalità. Se vogliamo aggiungere qualche funzionalità a ClickHouse, dobbiamo aumentare questo numero. Cioè, nella versione 20.4 ClickHouse funzionerà ancora meglio. La terza cifra è 20.3.4. Qui 4 è il numero di versioni di patch in cui non abbiamo aggiunto nuove funzionalità, ma corretto alcuni bug. E 4 significa che l'abbiamo fatto quattro volte.

Non pensare che questo sia qualcosa di terribile. Di solito l'utente può installare la versione più recente e funzionerà senza problemi con un tempo di attività annuale. Ma immagina che in qualche funzione per l'elaborazione delle bitmap, aggiunta dai nostri compagni cinesi, il server si blocchi quando si passano argomenti errati. Abbiamo la responsabilità di risolvere questo problema. Rilasceremo una nuova versione patch e ClickHouse diventerà più stabile.

Se hai ClickHouse in esecuzione in produzione e viene rilasciata una nuova versione di ClickHouse con funzionalità aggiuntive, ad esempio la 20.4.1 è la prima, non affrettarti a metterla in produzione il primo giorno. Perché è addirittura necessario? Se non usi già ClickHouse, puoi installarlo e molto probabilmente andrà tutto bene. Ma se ClickHouse funziona già stabilmente, tieni d'occhio le patch e gli aggiornamenti per vedere quali problemi stiamo risolvendo.

Kirill Shvakov: Vorrei aggiungere qualcosa sugli ambienti di test. Tutti hanno molta paura degli ambienti di test e per qualche motivo credono che se si dispone di un cluster ClickHouse molto grande, l'ambiente di test dovrebbe essere almeno dieci volte più piccolo. Non è affatto così.

Posso dirtelo dal mio esempio. Ho un progetto e c'è ClickHouse. Il nostro ambiente di test è proprio per lui: si tratta di una piccola macchina virtuale di Hetzner per venti euro, dove viene distribuito assolutamente tutto. Per fare ciò, in Ansible disponiamo della completa automazione e quindi, in linea di principio, non fa differenza dove andare: sui server hardware o semplicemente implementarli in macchine virtuali.

Cosa si può fare? Sarebbe carino fornire un esempio nella documentazione di ClickHouse su come distribuire un piccolo cluster a casa propria: in Docker, in LXC, magari creare un playbook Ansible, perché persone diverse hanno distribuzioni diverse. Questo semplificherà molto. Quando prendi e distribuisci un cluster in cinque minuti, è molto più semplice provare a capire qualcosa. Questo è molto più conveniente, perché passare a una versione di produzione che non hai testato è una strada che non porta da nessuna parte. A volte funziona e a volte no. E quindi sperare nel successo è un male.

Maxim Kotyakov, ingegnere senior di backend Avito: Aggiungerò qualcosa sugli ambienti di test da una serie di problemi affrontati dalle grandi aziende. Disponiamo di un cluster di accettazione ClickHouse a tutti gli effetti; in termini di schemi di dati e impostazioni, è una copia esatta di ciò che è in produzione. Questo cluster viene distribuito in contenitori abbastanza fatiscenti con un minimo di risorse. Scriviamo lì una certa percentuale dei dati di produzione, fortunatamente è possibile replicare il flusso in Kafka. Tutto lì è sincronizzato e scalato, sia in termini di capacità che di flusso, e, in teoria, a parità di altre condizioni, dovrebbe comportarsi come la produzione in termini di parametri. Tutto ciò che è potenzialmente esplosivo viene prima fatto rotolare su questo supporto e lasciato lì per diversi giorni finché non è pronto. Ma naturalmente questa soluzione è costosa, difficile e ha costi di supporto diversi da zero.

Aleksej Milovidov: Ti dirò com'è l'ambiente di test dei nostri amici di Yandex.Metrica. Un cluster aveva più di 600 server, un altro ne aveva 360 e ce n'è un terzo e diversi cluster. L'ambiente di test per uno di essi è costituito semplicemente da due frammenti con due repliche ciascuno. Perché due frammenti? In modo che tu non sia solo. E dovrebbero esserci anche delle repliche. Solo un certo importo minimo che ti puoi permettere.

Questo ambiente di test ti consente di verificare se le tue query funzionano e se qualcosa di grave non funziona. Ma spesso sorgono problemi di natura completamente diversa, quando tutto funziona, ma ci sono alcuni piccoli cambiamenti nel carico.

Lasciate che vi faccia un esempio. Abbiamo deciso di installare una nuova versione di ClickHouse. È stato pubblicato in un ambiente di test, sono stati completati test automatizzati nello stesso Yandex.Metrica, che confrontano i dati sulla vecchia versione e su quella nuova, eseguendo l'intera pipeline. E, naturalmente, test ecologici del nostro CI. Altrimenti non avremmo nemmeno proposto questa versione.

Va tutto bene. Stiamo iniziando a passare alla produzione. Ricevo un messaggio che il carico sui grafici è aumentato più volte. Stiamo ripristinando la versione. Guardo il grafico e vedo: il carico in realtà è aumentato più volte durante il lancio, ed è diminuito nuovamente durante il lancio. Quindi abbiamo iniziato a ripristinare la versione. E il carico aumentava allo stesso modo e diminuiva allo stesso modo. Quindi la conclusione è questa: il carico è aumentato a causa del layout, niente di sorprendente.

Quindi è stato difficile convincere i colleghi a installare la nuova versione. Dico: “Va bene, tira fuori. Incrociamo le dita, tutto funzionerà. Ora il carico sui grafici è aumentato, ma va tutto bene. Tenere duro." In generale, l'abbiamo fatto e basta: la versione è stata rilasciata per la produzione. Ma quasi con ogni layout sorgono problemi simili.

Si suppone che Kill query interrompa le query, ma non è così. Perché?

Un utente, una specie di analista, è venuto da me e ha creato una richiesta che inserisce il mio cluster ClickHouse. Alcuni nodi o l'intero cluster, a seconda della replica o del frammento a cui è stata inviata la richiesta. Vedo che tutte le risorse della CPU su questo server sono in uno scaffale, tutto è rosso. Allo stesso tempo, ClickHouse stessa risponde alle richieste. E scrivo: “Per favore, mostrami, elenco dei processi, quale richiesta ha generato questa follia”.

Trovo questa richiesta e le scrivo kill. E vedo che non succede nulla. Il mio server è su uno scaffale, ClickHouse mi dà alcuni comandi, mostra che il server è vivo e tutto va alla grande. Ma ho un degrado in tutte le richieste degli utenti, il degrado inizia con i record in ClickHouse e la mia query di eliminazione non funziona. Perché? Pensavo che kill query avrebbe dovuto uccidere le query, ma non è così.

Ora ci sarà una risposta piuttosto strana. Il punto è che kill query non uccide le query.

Kill query seleziona una piccola casella chiamata "Voglio che questa query venga eliminata". E la richiesta stessa esamina questo flag durante l'elaborazione di ciascun blocco. Se è impostato, la richiesta smette di funzionare. Si scopre che nessuno uccide la richiesta, lui stesso deve controllare tutto e fermarsi. E questo dovrebbe funzionare in tutti i casi in cui la richiesta si trova nello stato di elaborazione di blocchi di dati. Elaborerà il successivo blocco di dati, controllerà il flag e si fermerà.

Questo non funziona nei casi in cui la richiesta è bloccata su alcune operazioni. È vero, molto probabilmente non è il tuo caso, perché, secondo te, utilizza moltissime risorse del server. È possibile che ciò non funzioni nel caso dell'ordinamento esterno e in alcuni altri dettagli. Ma in generale questo non dovrebbe accadere, è un bug. E l'unica cosa che posso consigliare è aggiornare ClickHouse.

Come calcolare il tempo di risposta sotto carico di lettura?

Esiste una tabella che memorizza gli aggregati di articoli: vari contatori. Il numero di linee è di circa cento milioni. È possibile contare su un tempo di risposta prevedibile versando 1 RPS per 1 articoli?

A giudicare dal contesto, stiamo parlando del carico di lettura, perché non ci sono problemi con la scrittura: si possono inserire anche mille, anche centomila, e talvolta diversi milioni di righe.

Le richieste di lettura sono molto diverse. Nella selezione 1, ClickHouse può eseguire circa decine di migliaia di richieste al secondo, quindi anche le richieste per una chiave richiederanno già alcune risorse. E tali query puntuali saranno più difficili rispetto ad alcuni database di valori-chiave, poiché per ogni lettura è necessario leggere un blocco di dati per indice. Il nostro indice non affronta ogni record, ma ogni intervallo. Cioè, dovrai leggere l'intero intervallo: per impostazione predefinita sono 8192 righe. E dovrai decomprimere il blocco dati compresso da 64 KB a 1 MB. In genere, il completamento di tali query mirate richiede alcuni millisecondi. Ma questa è l'opzione più semplice.

Proviamo un po' di semplice aritmetica. Se moltiplichi pochi millisecondi per mille, ottieni pochi secondi. È come se fosse impossibile tenere il passo con mille richieste al secondo, ma in realtà è possibile, perché abbiamo diversi core di processore. Quindi, in linea di principio, ClickHouse a volte può contenere 1000 RPS, ma per richieste brevi, specificamente mirate.

Se devi ridimensionare un cluster ClickHouse in base al numero di richieste semplici, ti consiglio la cosa più semplice: aumentare il numero di repliche e inviare le richieste a una replica casuale. Se una replica contiene cinquecento richieste al secondo, il che è del tutto realistico, tre repliche ne gestiranno mille e mezzo.

A volte, ovviamente, puoi configurare ClickHouse per il numero massimo di letture di punti. Cosa è necessario per questo? Il primo è ridurre la granularità dell'indice. In questo caso, non dovrebbe essere ridotto a uno, ma in base al fatto che il numero di voci nell'indice sarà di diversi milioni o decine di milioni per server. Se la tabella ha cento milioni di righe, la granularità può essere impostata su 64.

È possibile ridurre la dimensione del blocco compresso. Ci sono impostazioni per questo dimensione minima del blocco compresso, dimensione massima del blocco di compressione. Possono essere ridotti, riempiti di dati e quindi le query mirate saranno più veloci. Tuttavia, ClickHouse non è un database di valori-chiave. Un gran numero di piccole richieste è un antipattern di carico.

Kirill Shvakov: Darò consigli nel caso in cui ci siano conti ordinari lì. Questa è una situazione abbastanza standard quando ClickHouse memorizza una sorta di contatore. Ho un utente, viene da questo o quel paese, e da qualche terzo campo, e devo aumentare qualcosa in modo incrementale. Prendi MySQL, crea una chiave univoca - in MySQL è una chiave duplicata e in PostgreSQL è un conflitto - e aggiungi un segno più. Funzionerà molto meglio.

Quando non disponi di molti dati, non ha molto senso utilizzare ClickHouse. Esistono database regolari e lo fanno bene.

Cosa posso modificare in ClickHouse in modo che siano presenti più dati nella cache?

Immaginiamo una situazione: i server hanno 256 GB di RAM, nella routine quotidiana ClickHouse impiega circa 60-80 GB, al massimo - fino a 130. Cosa può essere abilitato e ottimizzato in modo che più dati siano nella cache e, di conseguenza, ci sono meno viaggi sul disco?

In genere, la cache delle pagine del sistema operativo fa un buon lavoro. Se apri semplicemente la parte superiore, guarda lì memorizzato nella cache o libero - dice anche quanto è memorizzato nella cache - noterai che tutta la memoria libera viene utilizzata per la cache. E durante la lettura di questi dati, verranno letti non dal disco, ma dalla RAM. Allo stesso tempo, posso dire che la cache viene utilizzata in modo efficace perché sono i dati compressi ad essere memorizzati nella cache.

Tuttavia, se vuoi velocizzare ancora di più alcune semplici query, è possibile abilitare una cache nei dati decompressi all'interno di ClickHouse. È chiamato cache non compressa. Nel file di configurazione config.xml, imposta la dimensione della cache non compressa sul valore che ti serve: ti consiglio di non più della metà della RAM libera, perché il resto andrà nella cache della pagina.

Inoltre, sono disponibili due impostazioni del livello di richiesta. Prima impostazione - utilizzare la cache non compressa - include il suo utilizzo. Si consiglia di abilitarlo per tutte le richieste, tranne quelle pesanti, che possono leggere tutti i dati e svuotare la cache. E la seconda impostazione è qualcosa come il numero massimo di righe da utilizzare nella cache. Limita automaticamente le query di grandi dimensioni in modo che evitino la cache.

Come posso configurare storage_configuration per l'archiviazione nella RAM?

Nella nuova documentazione di ClickHouse ho letto la sezione relativa con memorizzazione dei dati. La descrizione contiene un esempio con SSD veloce.

Mi chiedo come sia possibile configurare la stessa cosa con la memoria calda del volume. E un'altra domanda. Come funziona la selezione con questa organizzazione dei dati, leggerà l'intero set o solo quello che si trova sul disco e questi dati sono compressi in memoria? E come funziona la sezione prewhere con un'organizzazione di dati di questo tipo?

Questa impostazione influisce sulla memorizzazione dei blocchi di dati e il loro formato non cambia in alcun modo.
Diamo uno sguardo più da vicino.

È possibile configurare l'archiviazione dei dati nella RAM. Tutto ciò che è configurato per il disco è il suo percorso. Si crea una partizione tmpfs montata su un percorso nel file system. Si specifica questo percorso come percorso per l'archiviazione dei dati per la partizione più calda, i pezzi di dati iniziano ad arrivare e vengono scritti lì, tutto va bene.

Ma non consiglio di farlo a causa della bassa affidabilità, anche se se disponi di almeno tre repliche in data center diversi, è possibile. Se succede qualcosa, i dati verranno ripristinati. Immaginiamo che il server sia stato improvvisamente spento e riacceso. La partizione è stata montata di nuovo, ma non c'era niente. Quando il server ClickHouse si avvia, vede che non ha questi pezzi, anche se, secondo i metadati di ZooKeeper, dovrebbero essere lì. Guarda quali repliche li hanno, li richiede e li scarica. In questo modo i dati verranno ripristinati.

In questo senso, l'archiviazione dei dati nella RAM non è fondamentalmente diversa dall'archiviazione su disco, perché quando i dati vengono scritti su disco, finiscono prima nella cache della pagina e successivamente vengono scritti fisicamente. Dipende dall'opzione di montaggio del file system. Ma per ogni evenienza, dirò che ClickHouse non si sincronizza durante l'inserimento.

In questo caso, i dati nella RAM vengono memorizzati esattamente nello stesso formato del disco. La query di selezione allo stesso modo seleziona i pezzi che devono essere letti, seleziona gli intervalli di dati necessari nei pezzi e li legge. E prewhere funziona esattamente allo stesso modo, indipendentemente dal fatto che i dati fossero nella RAM o su disco.

Fino a quale numero di valori univoci la bassa cardinalità è efficace?

La cardinalità bassa è progettata in modo intelligente. Compila dizionari di dati, ma sono locali. In primo luogo, ci sono dizionari diversi per ogni pezzo e, in secondo luogo, anche all'interno di un pezzo possono essere diversi per ogni intervallo. Quando il numero di valori univoci raggiunge una soglia – un milione, credo – il dizionario viene semplicemente accantonato e ne viene creato uno nuovo.

La risposta è in generale: per ogni intervallo locale, ad esempio per ogni giorno, fino a un milione di valori univoci è efficace la bassa cardinalità. Successivamente ci sarà semplicemente un fallback, in cui verranno utilizzati molti dizionari diversi e non uno solo. Funzionerà più o meno come una normale colonna di stringhe, forse un po' meno efficiente, ma non ci sarà alcun grave degrado delle prestazioni.

Quali sono le migliori pratiche per la ricerca full-text in una tabella con cinque miliardi di righe?

Ci sono risposte diverse. Il primo è dire che ClickHouse non è un motore di ricerca full-text. A questo scopo esistono sistemi speciali, ad es. elasticsearch и Sfinge. Tuttavia, vedo sempre più persone affermare che stanno passando da Elasticsearch a ClickHouse.

Perché succede questo? Lo spiegano con il fatto che Elasticsearch cessa di far fronte al carico su alcuni volumi, a partire dalla costruzione degli indici. Gli indici diventano troppo ingombranti e se trasferisci semplicemente i dati su ClickHouse, si scopre che vengono archiviati in modo molto più efficiente in termini di volume. Allo stesso tempo, le query di ricerca spesso non erano tali da rendere necessario trovare qualche frase nell'intero volume di dati, tenendo conto della morfologia, ma di quelle completamente diverse. Ad esempio, trova una sequenza successiva di byte nei log delle ultime ore.

In questo caso, crei un indice in ClickHouse, il cui primo campo sarà la data e l'ora. E il limite massimo di dati sarà basato sull'intervallo di date. All'interno dell'intervallo di date selezionato, di norma, è già possibile effettuare una ricerca full-text, anche utilizzando il metodo brute force utilizzando like. L'operatore like in ClickHouse è l'operatore like più efficiente che puoi trovare. Se trovi qualcosa di meglio, dimmelo.

Ma comunque, è una scansione completa. E la scansione completa può essere lenta non solo sulla CPU, ma anche sul disco. Se all'improvviso hai un terabyte di dati al giorno e cerchi una parola durante il giorno, dovrai scansionare il terabyte. E probabilmente si trova su normali dischi rigidi e alla fine verranno caricati in modo tale che non sarai in grado di accedere a questo server tramite SSH.

In questo caso, sono pronto a offrire un altro piccolo trucco. È sperimentale: potrebbe funzionare, potrebbe non funzionare. ClickHouse dispone di indici full-text sotto forma di filtri Bloom trigrammi. I nostri colleghi di Arenadata hanno già provato questi indici e spesso funzionano esattamente come previsto.

Per usarli correttamente, dovresti avere una buona conoscenza di come funzionano esattamente: cos'è un filtro Bloom trigramma e come sceglierne la dimensione. Posso dire che aiuteranno per domande su alcune frasi rare, sottostringhe che raramente si trovano nei dati. In questo caso, i sottointervalli verranno selezionati tramite indici e verranno letti meno dati.

Recentemente, ClickHouse ha aggiunto funzioni ancora più avanzate per la ricerca full-text. Si tratta, in primo luogo, della ricerca di un gruppo di sottostringhe contemporaneamente in un unico passaggio, comprese le opzioni che fanno distinzione tra maiuscole e minuscole, senza distinzione tra maiuscole e minuscole, con supporto per UTF-8 o solo per ASCII. Scegli quello più efficace di cui hai bisogno.

È stata inoltre visualizzata la ricerca di più espressioni regolari in un unico passaggio. Non è necessario scrivere X come una sottostringa o X come un'altra sottostringa. Scrivi subito e tutto viene fatto nel modo più efficiente possibile.

Terzo, ora c'è una ricerca approssimativa per le espressioni regolari e una ricerca approssimativa per le sottostringhe. Se qualcuno ha scritto male una parola, verrà cercata la corrispondenza massima.

Qual è il modo migliore per organizzare l'accesso a ClickHouse per un gran numero di utenti?

Raccontaci come organizzare al meglio l'accesso per un gran numero di consumatori e analisti. Come formare una coda, dare priorità al numero massimo di query simultanee e con quali strumenti?

Se il cluster è sufficientemente grande, una buona soluzione sarebbe quella di creare altri due server, che diventeranno un punto di ingresso per gli analisti. Cioè non consentire agli analisti di accedere a shard specifici nel cluster, ma creare semplicemente due server vuoti, senza dati, e configurare su di essi i diritti di accesso. In questo caso, le impostazioni utente per le richieste distribuite vengono trasferite ai server remoti. Cioè, configuri tutto su questi due server e le impostazioni hanno effetto sull'intero cluster.

In linea di principio questi server non contengono dati, ma la quantità di RAM presente su di essi è molto importante per l'esecuzione delle richieste. Il disco può essere utilizzato anche per dati temporanei se è abilitata l'aggregazione esterna o l'ordinamento esterno.

È importante esaminare le impostazioni associate a tutti i limiti possibili. Se ora vado al cluster Yandex.Metrica come analista e faccio una richiesta seleziona il conteggio dei risultati, mi verrà immediatamente concessa un'eccezione secondo cui non posso eseguire la richiesta. Il numero massimo di righe che posso scansionare è cento miliardi e in totale ce ne sono cinquanta trilioni in una tabella del cluster. Questa è la prima limitazione.

Diciamo che rimuovo il limite di righe ed eseguo nuovamente la query. Quindi vedrò la seguente eccezione: impostazione abilitata indice di forza per data. Non posso completare la query se non ho specificato un intervallo di date. Non è necessario affidarsi agli analisti per specificarlo manualmente. Un caso tipico è quando viene scritto un intervallo di date in cui la data dell'evento è compresa tra le settimane. E poi hanno semplicemente specificato una parentesi nel posto sbagliato, e invece di e si è scoperto che era o - o corrispondenza dell'URL. Se non ci sono limiti, eseguirà la scansione della colonna URL e sprecherà solo un sacco di risorse.

Inoltre, ClickHouse ha due impostazioni di priorità. Sfortunatamente, sono molto primitivi. Uno è semplicemente chiamato priorità. Se priorità ≠ 0 e vengono eseguite richieste con una certa priorità, ma viene eseguita una richiesta con un valore di priorità inferiore a, che significa una priorità più alta, allora viene eseguita una richiesta con un valore di priorità maggiore, che significa una priorità più bassa , è semplicemente sospeso e non funzionerà affatto durante questo periodo.

Questa è un'impostazione molto rozza e non è adatta ai casi in cui il cluster ha un carico costante. Ma se hai richieste brevi e importanti che sono importanti e il cluster è per lo più inattivo, questa configurazione è adatta.

Viene richiamata l'impostazione di priorità successiva Priorità del thread del sistema operativo. Imposta semplicemente il valore gradevole per tutti i thread di esecuzione delle richieste per lo scheduler Linux. Funziona così così, ma funziona ancora. Se imposti il ​​valore nice minimo - è il valore più grande, e quindi la priorità più bassa - e imposti -19 per le richieste con priorità alta, la CPU consumerà le richieste a bassa priorità circa quattro volte meno di quelle ad alta priorità.

È inoltre necessario configurare il tempo massimo di esecuzione della richiesta, ad esempio cinque minuti. La velocità minima di esecuzione delle query è la cosa più interessante. Questa impostazione esiste da molto tempo ed è necessaria non solo per affermare che ClickHouse non rallenta, ma per forzarlo.

Immagina di impostare: se alcune query elaborano meno di un milione di righe al secondo, non puoi farlo. Ciò disonora il nostro buon nome, il nostro buon database. Vietiamolo e basta. In realtà ci sono due impostazioni. Uno è chiamato velocità di esecuzione minima - in righe al secondo, e il secondo è chiamato timeout prima di controllare la velocità di esecuzione minima - quindici secondi per impostazione predefinita. Cioè, sono possibili quindici secondi e poi, se è lento, lancia semplicemente un'eccezione e interrompi la richiesta.

È inoltre necessario impostare delle quote. ClickHouse ha una funzione di quota integrata che conta il consumo di risorse. Ma, sfortunatamente, non risorse hardware come CPU, dischi, ma risorse logiche: il numero di richieste elaborate, righe e byte letti. E puoi configurare, ad esempio, un massimo di cento richieste in cinque minuti e mille richieste all'ora.

Perché è importante? Perché alcune query di analisi verranno eseguite manualmente direttamente dal client ClickHouse. E tutto andrà bene. Ma se nella tua azienda sono presenti analisti avanzati, scriveranno uno script e potrebbe esserci un errore nello script. E questo errore farà sì che la richiesta venga eseguita in un ciclo infinito. Questo è ciò da cui dobbiamo proteggerci.

È possibile fornire i risultati di una query a dieci clienti?

Abbiamo diversi utenti a cui piace presentarci con richieste molto grandi nello stesso momento. La richiesta è ampia e, in linea di principio, viene eseguita rapidamente, ma poiché esistono molte richieste di questo tipo contemporaneamente, diventa molto dolorosa. È possibile eseguire la stessa richiesta arrivata dieci volte di seguito, una volta, e dare il risultato a dieci client?

Il problema è che non abbiamo i risultati della cache o della cache dei dati intermedi. C'è una cache di pagina del sistema operativo, che ti impedirà di leggere nuovamente i dati dal disco, ma, sfortunatamente, i dati verranno comunque decompressi, deserializzati e rielaborati.

Vorrei in qualche modo evitarlo, memorizzando nella cache i dati intermedi o allineando query simili in una sorta di coda e aggiungendo una cache dei risultati. Al momento abbiamo una richiesta pull in fase di sviluppo che aggiunge una cache delle richieste, ma solo per le sottoquery nelle sezioni in e join, ovvero la soluzione è incompleta.

Tuttavia, anche noi ci troviamo di fronte a una situazione del genere. Un esempio particolarmente canonico sono le query impaginate. C'è un rapporto, ha diverse pagine e c'è una richiesta per il limite 10. Quindi la stessa cosa, ma limite 10,10. Poi un'altra pagina successiva. E la domanda è: perché contiamo tutto questo ogni volta? Ma ora non c’è soluzione e non c’è modo di evitarlo.

Esiste una soluzione alternativa che viene posizionata come sidecar accanto a ClickHouse - Proxy ClickHouse.

Kirill Shvakov: ClickHouse Proxy ha un limitatore di velocità integrato e una cache dei risultati integrata. Lì sono state effettuate molte impostazioni perché si stava risolvendo un problema simile. Il proxy ti consente di limitare le richieste mettendole in coda e di configurare la durata della cache delle richieste. Se le richieste fossero realmente le stesse, Proxy le invierà più volte, ma andrà a ClickHouse una sola volta.

Nginx ha anche una cache nella versione gratuita e anche questa funzionerà. Nginx ha anche impostazioni secondo le quali, se le richieste arrivano contemporaneamente, rallenterà le altre fino al completamento di una. Ma è in ClickHouse Proxy che la configurazione viene eseguita molto meglio. È stato realizzato appositamente per ClickHouse, appositamente per queste richieste, quindi è più adatto. Bene, è facile da installare.

Che dire delle operazioni asincrone e delle viste materializzate?

Si verifica un problema relativo al fatto che le operazioni con il motore di riproduzione sono asincrone: prima i dati vengono scritti, quindi vengono compressi. Se una tavoletta materializzata con alcuni aggregati vive sotto il segno, su di essa verranno scritti dei duplicati. E se non esiste una logica complessa, i dati verranno duplicati. Cosa puoi fare al riguardo?

Esiste una soluzione ovvia: implementare un trigger su una determinata classe di matview durante un'operazione di collasso asincrono. Esistono soluzioni miracolose o piani per implementare funzionalità simili?

Vale la pena capire come funziona la deduplicazione. Quello che ti dirò ora non è rilevante per la domanda, ma nel caso valga la pena ricordarlo.

Quando si inserisce in una tabella replicata, si verifica la deduplicazione degli interi blocchi inseriti. Se reinserisci lo stesso blocco contenente lo stesso numero di righe nello stesso ordine, i dati vengono deduplicati. Riceverai "Ok" in risposta all'inserimento, ma in realtà verrà scritto un pacchetto di dati e non verrà duplicato.

Ciò è necessario per avere certezza. Se durante l'inserimento ricevi "Ok" significa che i tuoi dati sono stati inseriti. Se ricevi un errore da ClickHouse significa che non sono stati inseriti e devi ripetere l'inserimento. Ma se durante l'inserimento la connessione si interrompe, non saprai se i dati sono stati inseriti oppure no. L'unica possibilità è ripetere nuovamente l'inserimento. Se i dati sono stati effettivamente inseriti e poi li hai reinseriti, c'è la deduplicazione a blocchi. Ciò è necessario per evitare duplicati.

Ed è anche importante il modo in cui funziona per le visualizzazioni materializzate. Se i dati sono stati deduplicati quando inseriti nella tabella principale, non verranno inseriti nemmeno nella vista materializzata.

Ora riguardo alla domanda. La tua situazione è più complicata perché stai registrando duplicati di singole righe. Cioè, non è l'intero pacchetto ad essere duplicato, ma linee specifiche, che collassano sullo sfondo. In effetti, i dati verranno compressi nella tabella principale, ma i dati non compressi andranno nella vista materializzata e durante le unioni non accadrà nulla alle viste materializzate. Perché una vista materializzata non è altro che un trigger di inserimento. Durante le altre operazioni non accade nulla di aggiuntivo.

E non posso renderti felice qui. Devi solo cercare una soluzione specifica per questo caso. Ad esempio, è possibile riprodurlo in una vista materializzata e il metodo di deduplicazione potrebbe funzionare allo stesso modo. Ma sfortunatamente, non sempre. Se si sta aggregando, non funzionerà.

Kirill Shvakov: In passato avevamo anche la costruzione di stampelle. Si è verificato un problema relativo alle impressioni pubblicitarie e ci sono alcuni dati che possiamo mostrare in tempo reale: queste sono solo impressioni. Raramente vengono duplicati, ma se ciò accade, li comprimeremo comunque in seguito. E c'erano cose che non potevano essere duplicate: i clic e tutta questa storia. Ma volevo anche mostrarli quasi subito.

Come sono state realizzate le visualizzazioni materializzate? C'erano visualizzazioni in cui veniva scritto direttamente: veniva scritto su dati grezzi e scritto su visualizzazioni. Lì ad un certo punto i dati non sono molto corretti, vengono duplicati e così via. E c'è una seconda parte della tabella, dove sembrano esattamente identiche alle viste materializzate, cioè sono assolutamente identiche nella struttura. Di tanto in tanto ricalcoliamo i dati, contiamo i dati senza duplicati, scriviamo in quelle tabelle.

Abbiamo utilizzato l'API: non funzionerà manualmente in ClickHouse. E l'API appare: quando ho la data dell'ultima aggiunta alla tabella, dove è garantito che siano già stati calcolati i dati corretti, e fa una richiesta a una tabella e ad un'altra tabella. Da uno la richiesta seleziona fino ad un certo periodo di tempo, dall'altro ottiene ciò che non è stato ancora calcolato. E funziona, ma non solo tramite ClickHouse.

Se disponi di una sorta di API - per analisti, per utenti - allora, in linea di principio, questa è un'opzione. Conti sempre, conti sempre. Questo può essere fatto una volta al giorno o in un altro momento. Scegli tu stesso una gamma che non ti serve e non è critica.

ClickHouse ha molti log. Come posso vedere a colpo d'occhio tutto ciò che accade al server?

ClickHouse ha un numero molto elevato di registri diversi e questo numero è in aumento. Nelle nuove versioni alcuni di essi sono addirittura abilitati di default; nelle versioni precedenti devono essere abilitati durante l'aggiornamento. Tuttavia, ce ne sono sempre di più. In definitiva, mi piacerebbe vedere cosa sta succedendo al mio server adesso, magari su una sorta di dashboard di riepilogo.

Hai un team ClickHouse, o i team dei tuoi amici, che supportano alcune funzionalità di dashboard già pronti che visualizzeranno questi registri come un prodotto finito? In definitiva, anche solo guardare i log in ClickHouse è fantastico. Ma sarebbe molto interessante se fosse già predisposto sotto forma di cruscotto. Mi divertirei.

Esistono dashboard, sebbene non siano standardizzati. Nella nostra azienda, circa 60 team utilizzano ClickHouse e la cosa più strana è che molti di loro hanno dashboard realizzate da loro stessi e leggermente diverse. Alcuni team utilizzano un'installazione interna di Yandex.Cloud. Esistono alcuni report già pronti, anche se non tutti quelli necessari. Altri ne hanno uno proprio.

I miei colleghi di Metrica hanno la propria dashboard in Grafana e io ho la mia per il loro cluster. Sto esaminando cose come il cache hit per la cache serif. E ancora più difficile è che utilizziamo strumenti diversi. Ho creato la mia dashboard utilizzando uno strumento molto vecchio chiamato Graphite-web. È completamente brutto. E lo uso ancora così, anche se Grafana probabilmente sarebbe più comoda e bella.

La cosa fondamentale nei dashboard è la stessa. Queste sono le metriche di sistema per il cluster: CPU, memoria, disco, rete. Altri: numero di richieste simultanee, numero di unioni simultanee, numero di richieste al secondo, numero massimo di blocchi per partizioni di tabella MergeTree, ritardo di replica, dimensione della coda di replica, numero di righe inserite al secondo, numero di blocchi inseriti al secondo. Questo è tutto ciò che si ottiene non dai log, ma dalle metriche.

Vladimir Kolobaev: Alexey, vorrei correggerlo un po '. C'è Grafana. Grafana ha un'origine dati, che è ClickHouse. Cioè posso fare richieste da Grafana direttamente a ClickHouse. ClickHouse ha una tabella con i log, è uguale per tutti. Di conseguenza, voglio accedere a questa tabella di registro in Grafana e vedere le richieste effettuate dal mio server. Sarebbe fantastico avere una dashboard come questa.

L'ho pedalato io stesso. Ma ho una domanda: se è tutto standardizzato e Grafana è utilizzato da tutti, perché Yandex non ha una dashboard così ufficiale?

Kirill Shvakov: In effetti, l'origine dati che va a ClickHouse ora supporta Altinity. E voglio solo dare un vettore di dove scavare e chi spingere. Puoi chiedere a loro, perché Yandex continua a produrre ClickHouse e non la storia che lo circonda. Altinity è la principale azienda che attualmente promuove ClickHouse. Non lo abbandoneranno, ma lo sosterranno. Perché, in linea di principio, per caricare una dashboard sul sito Grafana, devi solo registrarti e caricarla: non ci sono problemi particolari.

Aleksej Milovidov: Nell'ultimo anno, ClickHouse ha aggiunto molte funzionalità di profilazione delle query. Sono disponibili metriche per ogni richiesta sull'utilizzo delle risorse. E proprio di recente abbiamo aggiunto un query profiler di livello ancora più basso per vedere dove spende una query ogni millisecondo. Ma per utilizzare questa funzionalità devo aprire il client della console e digitare una richiesta, cosa che dimentico sempre. L'ho salvato da qualche parte e continuo a dimenticare dove esattamente.

Vorrei che ci fosse uno strumento che dicesse semplicemente: ecco le tue query pesanti, raggruppate per classe di query. Ne ho premuto uno e mi hanno detto che è per questo che è pesante. Al momento non esiste una soluzione del genere. Ed è davvero piuttosto strano che quando le persone mi chiedono: "Dimmi, ci sono dashboard già pronte per Grafana?", Io dico: "Vai sul sito Grafana, c'è una community "Dashboards" e c'è una dashboard da Dimka, c'è un cruscotto di Kostyan. Non so cosa sia, non l’ho usato personalmente.”

Come influenzare le fusioni in modo che il server non si blocchi in OOM?

Ho una tabella, c'è solo una partizione nella tabella, è ReplacingMergeTree. Ci scrivo dati da quattro anni. Avevo bisogno di modificarlo ed eliminare alcuni dati.

L'ho fatto e durante l'elaborazione di questa richiesta, tutta la memoria su tutti i server del cluster è stata consumata e tutti i server del cluster sono entrati in OOM. Poi si sono alzati tutti insieme, hanno iniziato a unire questa stessa operazione, questo blocco di dati, e sono caduti di nuovo in OOM. Poi si rialzarono e caddero di nuovo. E questa cosa non si è fermata.

Poi si è scoperto che in realtà si trattava di un bug risolto dai ragazzi. È molto bello, grazie mille. Ma rimaneva un residuo. E ora, quando penso di realizzare una sorta di unione nella tabella, mi viene una domanda: perché non posso in qualche modo influenzare queste unioni? Ad esempio, limitali alla quantità di RAM richiesta o, in linea di principio, alla quantità che elaborerà questa particolare tabella.

Ho una tabella chiamata "Metriche", elaborala per me in due thread. Non c'è bisogno di creare dieci o cinque fusioni in parallelo, fallo in due. Penso di avere memoria sufficiente per due, ma potrebbe non essere sufficiente per elaborarne dieci. Perché la paura rimane? Perché la tabella sta crescendo e un giorno mi troverò di fronte a una situazione che, in linea di principio, non è più dovuta a un bug, ma perché i dati cambieranno in una quantità così grande che semplicemente non avrò abbastanza memoria sul server. E poi il server si bloccherà in OOM durante la fusione. Inoltre, posso annullare la mutazione, ma Merji non c'è più.

Sai, durante la fusione, il server non cadrà in OOM, perché durante la fusione, la quantità di RAM viene utilizzata solo per un piccolo intervallo di dati. Quindi tutto andrà bene indipendentemente dalla quantità di dati.

Vladimir Kolobaev: Bene. Qui il momento è tale che dopo che il bug è stato risolto, ho scaricato una nuova versione per me, e su un altro tavolo, più piccolo, dove ci sono molte partizioni, ho eseguito un'operazione simile. E durante la fusione sul server sono stati bruciati circa 100 GB di RAM. Ne avevo 150 occupati, 100 mangiati e una finestra da 50 GB rimasta, quindi non sono caduto in OOM.

Cosa mi protegge attualmente dal cadere in OOM se consuma effettivamente 100 GB di RAM? Cosa fare se all'improvviso la RAM sui merge si esaurisce?

Aleksej Milovidov: Esiste un problema tale che il consumo di RAM specifico per la fusione non è limitato. E il secondo problema è che se è stata assegnata una sorta di fusione, questa deve essere eseguita perché viene registrata nel registro di replica. Il registro di replica contiene le azioni necessarie per portare la replica in uno stato coerente. Se non si effettuano manipolazioni manuali che effettueranno il rollback di questo registro di replica, l'unione dovrà essere eseguita in un modo o nell'altro.

Naturalmente, non sarebbe superfluo avere una limitazione della RAM che “per ogni evenienza” protegga da OOM. Non aiuterà il completamento dell'unione, ricomincerà, raggiungerà una certa soglia, genererà un'eccezione e poi ricomincerà: non ne verrà fuori nulla di buono. Ma in linea di principio sarebbe utile introdurre questa restrizione.

Come verrà sviluppato il driver Golang per ClickHouse?

Il driver Golang, scritto da Kirill Shvakov, è ora ufficialmente supportato dal team ClickHouse. Lui nel repository ClickHouse, ora è grande e reale.

Una piccola nota. Esiste un meraviglioso e amato deposito di forme normali di ordine infinito: questo è Vertica. Hanno anche il proprio driver Python ufficiale, supportato dagli sviluppatori Vertica. E più volte è successo che le versioni di archiviazione e le versioni del driver divergessero in modo abbastanza drammatico e il driver ad un certo punto smettesse di funzionare. E il secondo punto. Il supporto per questo driver ufficiale, mi sembra, viene effettuato dal sistema "nipple": scrivi loro un problema e si blocca per sempre.

Ho due domande. Ora il driver Golang di Kirill è quasi il modo predefinito per comunicare da Golang con ClickHouse. A meno che qualcuno non comunichi ancora tramite l'interfaccia http perché gli piace così. Come procederà lo sviluppo di questo driver? Verrà sincronizzato con eventuali modifiche importanti nel repository stesso? E qual è la procedura per considerare un problema?

Kirill Shvakov: Il primo è come tutto è organizzato burocraticamente. Questo punto non è stato discusso, quindi non ho nulla a cui rispondere.

Per rispondere alla domanda sul problema, abbiamo bisogno di una piccola storia del conducente. Ho lavorato per un'azienda che aveva molti dati. Era uno spinner pubblicitario con un numero enorme di eventi che dovevano essere archiviati da qualche parte. E ad un certo punto è apparso ClickHouse. L'abbiamo riempito di dati e all'inizio tutto andava bene, ma poi ClickHouse si è bloccato. In quel momento abbiamo deciso che non ne avevamo bisogno.

Un anno dopo, siamo tornati all'idea di utilizzare ClickHouse e avevamo bisogno di scrivere lì i dati in qualche modo. Il messaggio introduttivo è stato questo: l'hardware è molto debole, le risorse sono poche. Ma noi abbiamo sempre lavorato così, e quindi abbiamo guardato verso il protocollo nativo.

Dato che lavoravamo a Go, era chiaro che avevamo bisogno di un pilota Go. Lo facevo quasi a tempo pieno: era il mio compito lavorativo. L'abbiamo portato fino a un certo punto e in linea di principio nessuno dava per scontato che qualcun altro oltre a noi lo avrebbe usato. Poi è arrivato CloudFlare con esattamente lo stesso problema e per un po' di tempo abbiamo lavorato con loro senza problemi, perché avevano gli stessi compiti. Inoltre, lo abbiamo fatto sia in ClickHouse che nel driver.

Ad un certo punto ho semplicemente smesso di farlo, perché la mia attività in termini di ClickHouse e di lavoro è leggermente cambiata. Pertanto le questioni non sono chiuse. Periodicamente, le persone che hanno bisogno di qualcosa si impegnano a utilizzare il repository. Poi guardo la richiesta pull e talvolta modifico anche qualcosa da solo, ma questo accade raramente.

Voglio tornare dall'autista. Diversi anni fa, quando tutto ebbe inizio, anche ClickHouse era diversa e con funzionalità diverse. Ora sappiamo come rifare il driver in modo che funzioni bene. Se ciò accade, la versione 2 sarà comunque incompatibile a causa delle stampelle accumulate.

Non so come organizzare questa faccenda. Io non ho molto tempo. Se alcune persone finiscono l'autista, posso aiutarle e dire loro cosa fare. Ma la partecipazione attiva di Yandex allo sviluppo del progetto non è stata ancora discussa.

Aleksej Milovidov: In effetti, non esiste ancora alcuna burocrazia su questi driver. L'unica cosa è che sono presentati a un'organizzazione ufficiale, ovvero questo driver è riconosciuto come la soluzione predefinita ufficiale per Go. Ci sono alcuni altri driver, ma vengono forniti separatamente.

Non abbiamo alcuno sviluppo interno per questi driver. La domanda è se possiamo assumere una singola persona, non per questo particolare conducente, ma per lo sviluppo di tutti i conducenti della comunità, oppure possiamo trovare qualcuno dall'esterno.

Il dizionario esterno non viene caricato dopo un riavvio con l'impostazione lazy_load abilitata. Cosa fare?

Abbiamo abilitato l'impostazione lazy_load e, dopo il riavvio del server, il dizionario non si carica da solo. Viene generato solo dopo che l'utente accede a questo dizionario. E la prima volta che accedo mi dà un errore. È possibile caricare in qualche modo automaticamente i dizionari utilizzando ClickHouse o è necessario controllarne sempre la disponibilità in modo che gli utenti non ricevano errori?

Forse abbiamo una vecchia versione di ClickHouse, quindi il dizionario non si è caricato automaticamente. Potrebbe essere così?

Innanzitutto, è possibile forzare il caricamento dei dizionari utilizzando una query dizionari di ricarica del sistema. In secondo luogo, per quanto riguarda l'errore: se il dizionario è già caricato, le query funzioneranno in base ai dati caricati. Se il dizionario non è ancora stato caricato, verrà caricato direttamente durante la richiesta.

Questo non è molto conveniente per i dizionari pesanti. Ad esempio, devi estrarre un milione di righe da MySQL. Qualcuno effettua una selezione semplice, ma questa selezione attenderà lo stesso milione di righe. Ci sono due soluzioni qui. Il primo è disattivare lazy_load. In secondo luogo, quando il server è attivo, prima di caricarlo, fallo dizionario di ricarica del sistema o semplicemente esegui una query che utilizza un dizionario. Quindi il dizionario verrà caricato. È necessario controllare la disponibilità dei dizionari con l'impostazione lazy_load abilitata, perché ClickHouse non li carica automaticamente.

La risposta all'ultima domanda è che la versione è vecchia oppure è necessario eseguire il debug.

Cosa fare con il fatto che il sistema ricarica i dizionari non carica nessuno dei tanti dizionari se almeno uno di essi si blocca con un errore?

C'è un'altra domanda sui dizionari di ricarica del sistema. Abbiamo due dizionari: uno non è caricato, il secondo è caricato. In questo caso, i dizionari di ricarica del sistema non caricano alcun dizionario ed è necessario caricarne uno specifico punto per punto utilizzando il dizionario di ricarica del sistema. È legato anche alla versione ClickHouse?

Voglio farti felice. Questo comportamento stava cambiando. Ciò significa che se aggiorni ClickHouse, anche questo cambierà. Se non sei soddisfatto del tuo comportamento attuale dizionari di ricarica del sistema, aggiorna e speriamo che cambi in meglio.

Esiste un modo per configurare i dettagli nella configurazione di ClickHouse, ma non visualizzarli in caso di errori?

La domanda successiva riguarda gli errori relativi al dizionario, vale a dire i dettagli. Abbiamo specificato i dettagli di connessione nella configurazione ClickHouse per il dizionario e, se si verifica un errore, riceviamo questi dettagli e la password in risposta.

Abbiamo risolto questo errore aggiungendo dettagli alla configurazione del driver ODBC. Esiste un modo per configurare i dettagli nella configurazione di ClickHouse, ma non mostrare questi dettagli in caso di errori?

La vera soluzione qui è specificare queste credenziali in odbc.ini e in ClickHouse stessa specificare solo il nome dell'origine dati ODBC. Ciò non accadrà per altre fonti di dizionari: né per il dizionario con MySQL, né per gli altri, non dovresti vedere la password quando ricevi un messaggio di errore. Guarderò anche per ODBC: se esiste, devi solo rimuoverlo.

Bonus: sfondi per Zoom dalle riunioni

Facendo clic sull'immagine, per i lettori più persistenti si apriranno sfondi bonus degli incontri. Spegniamo il fuoco insieme alle mascotte della tecnologia Avito, conferiamo con i colleghi della stanza dell'amministratore di sistema o del club di computer della vecchia scuola e conduciamo riunioni quotidiane sotto il ponte sullo sfondo dei graffiti.

ClickHouse per utenti esperti in domande e risposte

Fonte: habr.com

Aggiungi un commento