スケーリング
この例では、スケールするシンプルな ClickHouse クラスターのセットアップ方法を学びます。 ここでは 5 台のサーバーを構成します。うち 2 台はデータのシャーディングに使用し、 残りの 3 台はコーディネーション(調停)に使用します。
これからセットアップするクラスターのアーキテクチャは、以下のとおりです。

ClickHouse Server と ClickHouse Keeper を同じサーバー上で動かすことも可能ですが、 本番環境では ClickHouse Keeper 用に 専用 ホストを使用することを強く推奨します。 この例でもその構成を用いて説明します。
Keeper サーバーは小さめの構成でも問題なく、各 Keeper サーバーあたり 4GB の RAM があれば、 ClickHouse Server 群が大きくなるまでは一般的には十分です。
前提条件
- 以前に ローカル ClickHouse サーバー をセットアップしたことがある
- ClickHouse の 設定ファイル など、基本的な設定に関する概念に慣れている
- 手元のマシンに Docker がインストールされている
ディレクトリ構造とテスト環境のセットアップ
以下の手順では、クラスターをゼロからセットアップする方法を順を追って説明します。これらの手順をスキップしてすぐにクラスターを起動したい場合は、examples リポジトリの 'docker-compose-recipes' ディレクトリ からサンプルファイルを取得できます。
このチュートリアルでは、Docker composeを使用してClickHouseクラスタをセットアップします。このセットアップは、個別のローカルマシン、仮想マシン、クラウドインスタンスでも動作するように変更可能です。
この例のディレクトリ構造をセットアップするには、以下のコマンドを実行します:
以下の docker-compose.yml ファイルを clickhouse-cluster ディレクトリに追加します:
以下のサブディレクトリとファイルを作成します:
config.dディレクトリには ClickHouse サーバーの設定ファイルconfig.xmlが含まれており、 各 ClickHouse ノード向けのカスタム設定がここで定義されます。 この設定は、すべての ClickHouse インストールに付属するデフォルトの ClickHouse 設定ファイルconfig.xmlとマージされて使用されます。users.dディレクトリにはユーザー設定ファイルusers.xmlが含まれており、 ユーザーに対するカスタム設定がここで定義されます。 この設定は、すべての ClickHouse インストールに付属するデフォルトの ClickHouse 設定ファイルusers.xmlとマージされて使用されます。
独自の設定を記述する際には、/etc/clickhouse-server/config.xml および
etc/clickhouse-server/users.xml のデフォルト設定を直接変更するのではなく、
config.d および users.d ディレクトリを利用することがベストプラクティスです。
The line
config.d および users.d ディレクトリで定義された設定セクションが、デフォルトの config.xml および users.xml ファイルで定義されている設定セクションより優先されるようにします。
ClickHouseノードの設定
サーバーのセットアップ
次に、fs/volumes/clickhouse-{}/etc/clickhouse-server/config.dに配置されている各空の設定ファイルconfig.xmlを修正します。以下で強調表示されている行は、各ノードに固有の内容に変更する必要があります:
| ディレクトリ | ファイル |
|---|---|
fs/volumes/clickhouse-01/etc/clickhouse-server/config.d | config.xml |
fs/volumes/clickhouse-02/etc/clickhouse-server/config.d | config.xml |
上記の設定ファイルの各セクションについて、以下で詳細に説明します。
ネットワーキングとロギング
ネットワークインターフェースへの外部からの通信は、listen_host 設定を有効にすることで行えるようになります。これにより、ClickHouse サーバーホストには他のホストから接続できるようになります。
HTTP API 用のポートは 8123 に設定されています:
ClickHouse のネイティブプロトコルを使用した clickhouse-client と他のネイティブ ClickHouse ツール間、ならびに clickhouse-server と他の clickhouse-server 間の通信に用いられる TCP ポートは 9000 です。
ログ記録は <logger> ブロックで定義します。この設定例では、1000Mに達すると3回ローテーションするデバッグログが出力されます:
ログ設定の詳細については、デフォルトのClickHouse設定ファイルに含まれているコメントを参照してください。
クラスター設定
クラスタの設定は <remote_servers> ブロックで設定します。
ここでクラスタ名 cluster_2S_1R を定義しています。
<cluster_2S_1R></cluster_2S_1R> ブロックは、<shard></shard> および <replica></replica> 設定を使用してクラスタのレイアウトを定義し、分散DDLクエリのテンプレートとして機能します。分散DDLクエリは、ON CLUSTER 句を使用してクラスタ全体で実行されるクエリです。デフォルトでは分散DDLクエリは許可されていますが、allow_distributed_ddl_queries 設定により無効化することも可能です。
internal_replicationは、シャードごとにレプリカが1つのみであるため、デフォルトでfalseに設定されたままになっています。
各サーバーごとに、次のパラメータを指定します。
| Parameter | Description | Default Value |
|---|---|---|
host | リモートサーバーのアドレス。ドメイン名、IPv4 アドレス、または IPv6 アドレスのいずれかを使用できます。ドメイン名を指定した場合、サーバー起動時に DNS リクエストが行われ、その結果はサーバーの動作中保持されます。DNS リクエストが失敗した場合、サーバーは起動しません。DNS レコードを変更した場合は、サーバーを再起動する必要があります。 | - |
port | messenger の動作に使用する TCP ポート(設定ファイルの tcp_port。通常は 9000 に設定)。http_port と混同しないでください。 | - |
Keeper の設定
<ZooKeeper> セクションは、ClickHouse Keeper(または ZooKeeper)の実行場所を ClickHouse に指定します。
ClickHouse Keeper クラスタを使用する場合、クラスタの各 <node> を指定する必要があります。
ホスト名とポート番号はそれぞれ <host> タグと <port> タグを使用して指定します。
ClickHouse Keeperのセットアップは、チュートリアルの次のステップで説明されています。
ClickHouse KeeperをClickHouse Serverと同じサーバー上で実行することは可能ですが、本番環境では専用ホスト上で実行することを強く推奨します。
マクロの設定
また、<macros> セクションは、レプリケーテッドテーブルのパラメータ置換を定義するために使用されます。これらは system.macros に記載され、クエリ内で {shard} や {replica} などの置換を使用できます。
これらはクラスタの構成に応じて個別に定義する必要があります。
ユーザー設定
次に、fs/volumes/clickhouse-{}/etc/clickhouse-server/users.d に配置されている各空の設定ファイル users.xml を以下の内容で変更します:
| 目次 | ファイル |
|---|---|
fs/volumes/clickhouse-01/etc/clickhouse-server/users.d | users.xml |
fs/volumes/clickhouse-02/etc/clickhouse-server/users.d | users.xml |
この例では、簡略化のためデフォルトユーザーをパスワードなしで設定しています。 実際の運用環境では、この設定は推奨されません。
この例では、クラスター内のすべてのノードでusers.xmlファイルが同一です。
ClickHouse Keeperの設定
Keeperのセットアップ
レプリケーションを機能させるためには、ClickHouse Keeper クラスターをセットアップして 構成する必要があります。ClickHouse Keeper はデータレプリケーションのためのコーディネーションシステムを提供し、 ZooKeeper の代替として動作しますが、ZooKeeper を使用することも可能です。 ただし ClickHouse Keeper は、より強い保証と高い信頼性を提供し、ZooKeeper よりも少ないリソースで 動作するため推奨されます。高可用性とクォーラム維持のために、少なくとも 3 つの ClickHouse Keeper ノードを 実行することを推奨します。
ClickHouse Keeper はクラスター内の任意のノード上で ClickHouse と一緒に実行できますが、 スケーリングおよびデータベースクラスターとは独立した ClickHouse Keeper クラスターの管理を可能にするため、 専用ノード上で実行することを推奨します。
各 ClickHouse Keeper ノード用の keeper_config.xml ファイルを、
サンプルディレクトリのルートから次のコマンドを使用して作成します:
各ノードのディレクトリ fs/volumes/clickhouse-keeper-{}/etc/clickhouse-keeper に作成された空の設定ファイルを編集します。
以下のハイライトされた行を、各ノードに固有の設定となるように変更してください。
| ディレクトリ | ファイル |
|---|---|
fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper | keeper_config.xml |
fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper | keeper_config.xml |
fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper | keeper_config.xml |
各設定ファイルには、以下のような固有の設定が含まれています(下記参照)。
使用する server_id は、そのクラスタ内で該当する ClickHouse Keeper ノードごとに一意であり、
<raft_configuration> セクションで定義されているサーバーの <id> と一致している必要があります。
tcp_port は ClickHouse Keeper の クライアント が使用するポートです。
次のセクションでは、Raft 合意アルゴリズム の クォーラムに参加するサーバーを構成します。
ClickHouse Cloud は、シャードおよびレプリカの管理に伴う運用上の負担を取り除きます。 プラットフォームが高可用性の確保、レプリケーション、およびスケーリングに関する判断を自動的に行います。 コンピュートリソースとストレージは分離されており、需要に応じて自動的にスケールするため、手動での設定や継続的なメンテナンスは不要です。
セットアップのテスト
マシン上でDockerが実行されていることを確認してください。
cluster_2S_1Rディレクトリのルートからdocker-compose upコマンドを使用してクラスタを起動します:
dockerがClickHouseとKeeperのイメージをプルし、 その後コンテナを起動する様子が確認できます:
クラスタが稼働していることを確認するには、clickhouse-01 または clickhouse-02 のいずれかに接続し、以下のクエリを実行します。最初のノードへの接続コマンドは次のとおりです:
成功すると、ClickHouseクライアントのプロンプトが表示されます:
以下のクエリを実行して、各ホストに定義されているクラスタトポロジを確認します:
以下のクエリを実行して、ClickHouse Keeperクラスタのステータスを確認します:
mntr コマンドは、ClickHouse Keeper が稼働していることを確認し、
3 つの Keeper ノード間の関係に関する状態情報を取得するためにも一般的に使用されます。
この例で使用している構成では、3 つのノードが協調して動作しています。
ノード間でリーダーを選出し、残りのノードはフォロワーになります。
mntr コマンドは、パフォーマンスに関連する情報と、特定のノードが
フォロワーかリーダーかを示します。
Keeper に mntr コマンドを送信するには、netcat をインストールする必要がある場合があります。
ダウンロード情報については nmap.org のページを参照してください。
各 Keeper ノードのステータスを確認するために、clickhouse-keeper-01、clickhouse-keeper-02、
clickhouse-keeper-03 上のシェルから以下のコマンドを実行します。
clickhouse-keeper-01 用のコマンドは次のとおりです。
以下は、フォロワーノードからの応答例です。
以下は、リーダーノードからの応答例です。
これで、1つのシャードと2つのレプリカを持つClickHouseクラスタのセットアップが完了しました。 次のステップでは、クラスタにテーブルを作成します。
データベースを作成する
クラスタが正しくセットアップされ、実行されていることを確認したので、UK property pricesサンプルデータセットチュートリアルで使用されているものと同じテーブルを再作成します。このデータセットは、1995年以降にイングランドとウェールズで取引された不動産物件の価格データ約3,000万行で構成されています。
各ホストのクライアントに接続するには、以下の各コマンドを別々のターミナルタブまたはウィンドウから実行します:
各ホストのclickhouse-clientから以下のクエリを実行して、デフォルトのデータベース以外にデータベースが作成されていないことを確認してください:
clickhouse-01 クライアントから、ON CLUSTER 句を使用して以下の分散型 DDL クエリを実行し、uk という名前の新しいデータベースを作成します:
各ホストのクライアントから先ほどと同じクエリを再度実行し、clickhouse-01でのみクエリを実行したにもかかわらず、クラスタ全体でデータベースが作成されていることを確認できます。
クラスタ上にテーブルを作成する
データベースが作成されたので、次にテーブルを作成します。 任意のホストクライアントから以下のクエリを実行してください:
これはUK property pricesサンプルデータセットチュートリアルの元のCREATE文で使用されたクエリと同一です。ただし、ON CLUSTER句は除きます。
ON CLUSTER句は、CREATE、DROP、ALTER、RENAMEなどのDDL(Data Definition Language)クエリを分散実行するために設計されており、これらのスキーマ変更をクラスタ内のすべてのノードに適用します。
各ホストのクライアントから以下のクエリを実行し、クラスタ全体でテーブルが作成されていることを確認してください:
英国の不動産取引価格データを挿入する前に、各ホストから通常のテーブルにデータを挿入した際の動作を確認するため、簡単な実験を実施します。
いずれかのホストから次のクエリでテストデータベースとテーブルを作成します:
次に clickhouse-01 から以下の INSERT クエリを実行します:
clickhouse-02 に切り替えて、以下の INSERT クエリを実行します:
次に、clickhouse-01 または clickhouse-02 から以下のクエリを実行してください:
ReplicatedMergeTreeテーブルとは異なり、その特定のホストのテーブルに挿入された行のみが返され、両方の行が返されることはありません。
2つのシャードにまたがるデータを読み取るには、全シャードに対するクエリを処理できるインターフェースが必要です。このインターフェースは、SELECTクエリ実行時に両シャードのデータを結合し、INSERTクエリ実行時には両シャードへデータを挿入します。
ClickHouseでは、このインターフェースは分散テーブルと呼ばれ、Distributedテーブルエンジンを使用して作成します。その仕組みを見ていきましょう。
分散テーブルの作成
以下のクエリを使用して分散テーブルを作成します:
この例では、rand() 関数をシャーディングキーとして選択しており、
これによりデータの挿入がシャード全体にランダムに分散されます。
どちらのホストからでも分散テーブルをクエリすると、前の例とは異なり、両方のホストに挿入された2つの行がすべて返されます:
UK不動産価格データについても同様に実行します。任意のホストクライアントから、
以下のクエリを実行して、先ほどON CLUSTERで作成した既存のテーブルを使用した分散テーブルを作成してください:
分散テーブルへのデータ挿入
いずれかのホストに接続し、データを挿入します:
データが挿入されたら、分散テーブルを使用して行数を確認できます:
いずれかのホストで以下のクエリを実行すると、データがシャード間でほぼ均等に分散されていることが確認できます(挿入先のシャードの選択は rand() で設定されているため、結果が異なる可能性があります):
ホストの1つに障害が発生した場合、何が起こるでしょうか。clickhouse-01をシャットダウンして、これをシミュレートしてみましょう:
以下を実行してホストがダウンしていることを確認します:
次に、clickhouse-02 から、先ほど分散テーブルに対して実行したのと同じ select クエリを実行します:
残念ながら、このクラスタには耐障害性がありません。ホストの1つに障害が発生すると、クラスタは異常状態と見なされ、クエリは失敗します。これは、前の例で見たレプリケーテッドテーブルとは対照的です。レプリケーテッドテーブルでは、ホストの1つに障害が発生してもデータを挿入できました。
結論
このクラスタトポロジーの利点は、データが複数のホストに分散され、ノードあたりのストレージ使用量が半分になる点です。さらに重要な点として、クエリは両方のシャードにまたがって処理されるため、メモリ使用効率が高くなり、ホストあたりの I/O が削減されます。
このクラスタトポロジーの主な欠点は、もちろん、ホストの 1 つを失うとクエリを処理できなくなることです。
次の例では、スケーラビリティとフォールトトレランスの両方を提供する、2 つのシャードと 2 つのレプリカを持つクラスタのセットアップ方法を見ていきます。