ClickHouse

High Availability

ClickHouse e' un Columnar Database SQL, distribuito ed Open Source con ottime prestazioni sulle attivita' OLAP (On-Line Analytical Processing).
ClickHouse e' di semplice installazione, gestione ed utilizzo (SQL). Anche se di recente introduzione ha raggiunto una buona maturita' e completezza funzionale per essere utilizzato in ambienti di produzione.

In questa paginetta vediamo gli aspetti relativi all'HA (High Availability) di ClickHouse, sia dal punto di vista della base dati che da quello applicativo. E' infatti importante utilizzare le corrette configurazioni affinche' la base dati mantenga in modo consistente i dati su piu' nodi, ma anche perche' le applicazioni accedano in modo corretto per evitare SPOF (Single Point Of Failure).

Gli argomenti contenuti in questa pagina sono: Introduzione, Database HA: Replica, Application HA: CHproxy, HAproxy, JDBC, ...

Introduzione

ClickHouse e' un recente database colonnare adatto alle attivita' OLAP (On-Line Analytical Processing).
Come altri DB column-oriented ClickHouse e' migliaia di volte piu' veloce nelle query OLAP rispetto ad un DB relazionale tradizionale. Inoltre ClickHouse non presenta la latenza tipica di altri database NoSQL rispondendo in modo real time alle richieste semplici grazie a potenti algoritmi calcolo parallelo e di compressione dei dati.
Riassumendo ClickHouse trova la sua applicazione sia quando siano necessarie ottime prestazioni con query analitiche, sia quando sia necessario mantenere grandi quantita' di dati.

Per ogni tabella e' possibile scegliere un tipo di memorizzazione dei dati: l'Engine. ClickHouse utilizza diverse famiglie di Engine ma la piu' importante e' MergeTree ed i suoi derivati. Con il MergeTree i dati sono ordinati per Primary Key e viene eseguito il pruning delle query sulla partitioning key. In fase di inserimento i dati vengono scritti velocemente in parti (Parts) e quindi uniti (merge) successivamente da un thread asincrono.
La replica e' configurabile utilizzando Engine della famiglia MergeTree specializzati (eg. ReplicatedMergeTree), come vedremo meglio nel seguito.

ClickHouse utilizza diverse porte socket ma quella tipicamente utilizzata e' la 8123 che utilizza il protocollo HTTP/HTTPS.
ClickHouse puo' essere utilizzato su server singolo oppure configurato in cluster con shard e replica. Gli shard consentono di distribuire i dati e le elaborazioni per migliorare le prestazioni, mentre le repliche aggiornano gli stessi oggetti su piu' nodi in modo da garantire sempre la disponibilita' dei dati.
Grazie alla particolare struttura di memorizzazione dei dati le query eseguite in cluster scalano le prestazioni in modo lineare sul numero di shard utilizzati. Un cluster ClickHouse non e' elastico e vanno riconfigurate le tabelle per ridistribuire gli shard all'inserimento di un nuovo nodo.

La replica opera a livello di singola tabella ed e' indipendente dallo sharding. Le repliche sono di tipo asincrono ed aggiornate in modalita' multimaster; il numero minimo di repliche e' due.
Per la gestione di un cluster e' utilizzato di ZooKeeper, che e' fortemente consigliato quando il numero di nodi e' elevato e si utilizzano le repliche [NdA ZooKeeper non e' strettamente obbligatorio per lo sharding ma e' necessario per creare le repliche]. ZooKeeper va posto su nodi differente da quelli di ClickHouse poiche' ClickHouse tende ad monopolizzare il server quando esegue query pesanti.

Database HA: Cluster

E' possibile utilizzare piu' nodi in un cluster omogeneo ClickHouse. I server sono tra loro completamente indipendenti con una configurazione share nothing.
I nodi possono essere utilizzati sia per suddividere i dati in shard sia per salvarli piu' volte in replica. Le due fuzionalita' sono indipendenti e possono essere configurati tabella per tabella. E' quindi possibile avere una serie di tabelle replicate, una serie di tabelle in shard e tabelle locali ai singoli nodi ClickHouse.

La configurazione di un cluster non e' complessa ma e' necessario che tutti i nodi si conoscano e si parlino correttamente (eg. hostname, DNS, firewall ACL, ...). E' inoltre necessario disporre di un Ensemble ZooKeeper che registra le richieste e si occupa del coordinamento dei nodi.

Questa e' una configurazione completa di un cluster (con tre repliche):

<yandex> <remote_servers> <ch_cluster> <shard> <weight>1</weight> <internal_replication>false</internal_replication> <replica> <host>clickhouse01.xenialab.it</host> <port>9000</port> </replica> <replica> <host>clickhouse02.xenialab.it</host> <port>9000</port> </replica> <replica> <host>clickhouse03.xenialab.it</host> <port>9000</port> </replica> </shard> </ch_cluster> </remote_servers> <zookeeper> <node index="1"> <host>zoo1.xenialab.it</host> <port>2181</port> </node> <node index="2"> <host>zoo2.xenialab.it</host> <port>2181</port> </node> <node index="3"> <host>zoo3.xenialab.it</host> <port>2181</port> </node> </zookeeper> <macros incl="macros" optional="true" /> <distributed_ddl> <path>/clickhouse/task_queue/ddl</path> </distributed_ddl> </yandex>

Anche se un po' lungo il file configurazione non e' complesso: riporta l'elenco dei nodi del cluster suddivisi prima per shard [NdA solo uno in questo caso], poi per replica, gli estremi del cluster ZooKeeper, l'abilitazione delle macro e delle DDL distribuite.

Per semplificare la configurazione delle repliche e' anche opportuno utilizzare le macro che vanno configurate su ogni nodo [NdA attenzione ogni nodo ha la sua configurazione].

<yandex> <macros> <cluster>ch_cluster</cluster> <replica>clickhouse01</replica> <shard>1</shard> </macros> </yandex>

Eseguita la fase di configurazione e' possibile creare le repliche!

Replica

Una volta configurato il cluster e' possibile creare tabelle replicate.

La replica e' fondamentale per la distribuzione dei dati poiche' fornisce High Availability, Load Scaling ed una piu' semplice gestione delle migrazioni, update e manutenzioni.
La creazione e' molto semplice basta sostituire l'engine MergeTree() con ReplicatedMergeTree(). I due parametri aggiuntivi di ReplicatedMergeTree sono:

Ad esempio:


ENGINE = ReplicatedMergeTree('/clickhouse/{cluster}/tables/{shard}/DB_name_Table_name', '{replica}')

I valori tra le graffe vengono sostituiti con quanto definito nel file macros.xml sotto config.d. Grazie alla macro la DDL della tabella e' la stessa su ogni nodo pero' il file macro.xml cambia da un nodo all'altro. macro.xml e' l'unico file di configurazione che richiede delle modifiche se copiato da un nodo all'altro.

Su ogni nodo del cluster e' ora possibile interrogare la tabella in replica. Se avviene una modifica questa verra' replicata su tutti gli altri nodi in modo asincrono.

E' importante ricordare che la replica e' multimaster: quindi l'inserimento dei dati puo' avvenire su un un nodo qualsiasi anche in parallelo. Database piu' complessi hanno difficolta' nella gestione delle repliche multi-master... ma bisogna ricordare che ClickHouse esegue solo INSERT! [NdA in realta' vi sono anche le mutation e nelle versioni piu' recenti anch'esse sono gestite nelle repliche]
Utilizzare nodi in replica consente anche di scalare prestazionalmente sulle attivita' in lettura. Non vengono invece scalate le prestazioni per le scritture, per avere prestazioni che scalano anche in scrittura e' necessario attivare lo sharding.
Naturalmente per distribuire il carico le applicazioni debbono accedere a nodi differenti...

Application HA

Nei paragrafi precedenti abbiamo visto come impostare le repliche in ClickHouse ma per realizzare un'alta affidabilita' questi dati debbono essere accessibili in modo trasparente agli utenti.
Sono possibili diverse tecniche e nel seguito vedremo quelle piu' indicate per ClickHouse.

Una prima soluzione e' quella di lasciare scegliere alle applicazioni il nodo cui connettersi...
Questa modalita' presenta diversi difetti: ogni applicazione deve trattare le problematiche di nodi non raggiungibili, del bilanciamento

CHproxy

Chproxy e' un proxy HTTP Open Source specifico per ClickHouse.

CHproxy e' scritto in Go ed ha una serie di funzionalita' specifiche per ClickHouse oltre alle normali funzionalita' di un proxy: controllo dei nodi, limiti sugli accessi, politiche di bilanciamento, ...

L'installazione e' molto semplice: basta scaricare i binari.
La configurazione richiede un unico file:

server:
  http:
    listen_addr: ":9090"
    allowed_networks: ["10.20.30.0/24"]

users:
  - name: "default"
    to_cluster: "default"
    to_user: "default"

clusters:
  - name: "default"
    nodes: [
      "10.20.40.1:8123",
      "10.20.40.2:8123",
      "10.20.40.3:8123"]

Con la semplice configurazione dell'esempio il proxy ascolta sulla porta 9090 ed invia le richiesta ai tre server ClickHouse configurati.

HAproxy

HAProxy e' un proxy TCP/HTTP Open Source.

Noto per la velocita' e robustezza e' uno dei proxy piu' noti ed utilizzati non solo per il traffico HTTP ma per tutti i protocolli e per molti database.
Poiche' ClickHouse utilizza il protocollo HTTP il controllo da parte di HAProxy e' molto semplice. Ecco l'esempio per HAProxy (configurato nel file /etc/haproxy/haproxy.cfg):

listen clickhouse *:9090
    mode tcp
    option tcplog
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    balance roundrobin
    option httpchk GET /?user=default&query=SELECT%201
    http-check expect rstring 1
    server clickhouse01 10.20.40.1:8123 check port 8123 inter 2s rise 1 fall 2
    server clickhouse02 10.20.40.2:8123 check port 8123 inter 2s rise 1 fall 2
    server clickhouse03 10.20.40.3:8123 check port 8123 inter 2s rise 1 fall 2

JDBC Balancing

In realta' non e' strettamente necessario utilizzare un load balancer per distribuire il carico sulle diverse repliche. Per accedere ai nodi in cluster e' possibile utilizzare BalancedClickhouseDataSource nelle connessioni JDBC: in questo modo si accede ad un nodo scelto a random dalla lista dei nodi forniti.

Questa e' la soluzione piu' semplice ma richiede di distribuire l'elenco dei nodi del cluster sulle applicazioni.

Sharding

Anche se questa paginetta si e' occupata principalmente della replica e' importante ricordare la possibilita' di effetturare lo sharding dei dati con ClickHouse. La configurazione del cluster e' la stessa anche se lo sharding non richiede ZooKeeper.
Lo sharding, come la replica, e' definito per singola tabella.

Varie ed eventuali

Se si utilizza un Cluster durante gli upgrade semplicemente va aggiornato un nodo alla volta: in questo modo e' possibile effettuare l'aggiornamento senza disservizi. ZooKeeper, gestendo le repliche, si occupa dell'allineamento dei dati quando i nodi tornano attivi.
Deve comunque essere ricordato che le repliche sono asincrone e non vengono garantite le transazioni con ClickHouse.

Il documento Introduzione a ClickHouse contiene una presentazione sulle funzioni di base mentre il documento Architettura di ClickHouse ne presenta gli aspetti architetturali.


Titolo: ClickHouse HA
Livello: Avanzato (3/5)
Data: 31 Ottobre 2019 🎃 Halloween
Versione: 1.0.1 - 1 Aprile 2020 🐟
© Autore: mail [AT] meo.bogliolo.name, Umberto Signori