在本章節中,我們將會討論有關於建置一個具有分散式且容錯的ClickHouse資料庫叢集。
ClickHouse資料庫支援了分散式與複製(replica)資料的功能,但是官方文件對於此相關的功能並不是很直白地進行描述,以下我們將會描述此類的細節以及建置叢集所需要的設定。
資料分布(Data distribution)是將我們的資料集切成多個片段(shards),這些多個片段會儲存在不同的資料庫伺服器上。我們這裡不會討論資料分布的策略,但是我們將會專注在如何在節點之間存取不同資料片段。
資料複製(Data replication)是將資料從一個節點複製到多個設定的節點上,這樣可以確保當某個節點或網路損壞時,資料仍夠透過其他設定在叢集中健康的節點進行存取,這樣機制也可以改善查詢效能,因為允許在多個資料庫伺服器使用同樣的資料並進行處理平行的查詢,
我們在這章節中,假設已經會建置與設定ClickHouse資料庫伺服器的單一節點,若不會的話,可以先前安裝ClickHouse資料庫的章節進行了解、安裝與設定。
我們為了要建立分散資料的資料表,我們需要先設定下列的事項:
config.xml
檔案中有設定叫做remote_servers
,這個設定可以用來指定叢集清單中包含我們的資料片段,每個片段用來定義複製資料的清單且包含了伺服器的位址等資訊。default_database
參數是預設將Distributed
之資料表引擎的資料表放到哪個資料庫中,當建立資料表沒有指定資料庫的時候,預設就會將這類的資料表放入到該設定的資料庫中。host
參數是資料複製要儲存到哪些資料庫伺服器主機中。port
參數是資料複製要儲存到哪些庫伺服器主機的埠號。在資料片段內部中,可以一個片段對應到多個資料複製,資料會從第一個可使用的資料複製中進行存取。
在設定資料分散之前,先設定好虛擬主機之間的存取,假設有兩個節點分別在不同的虛擬主機上且每個虛擬主機上都裝有Ubuntu 18.04的Linux發行版本的作業系統以及ClickHouse資料庫。
在每個作業系統上面都已經安裝好ClickHouse資料庫,為了要讓這兩個資料庫之間都可以在區域網路上連的到,因此需要先知道且假設下列的事項:
虛擬機器A可以使用下列的方法設定監聽的位址改成:0.0.0.0,這樣就可以把設定在這個機器上的所有IPv4都可以監聽到,相關設定所執行的指令如下:
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# cat /etc/clickhouse-server/config.d/listen_host.xml
<clickhouse>
<listen_host>0.0.0.0</listen_host>
</clickhouse>
從上述的設定可以知道,我們在虛擬機器A上建立一個listen_host.xml
檔案覆寫既有的config.xml
檔案,這樣就完成讓虛擬機器A監聽在0.0.0.0上面了;同理,虛擬機器B也是這樣的設定。
都設定完成之後,接著使用下列的指令將每一台的資料庫伺服器服務進行重新啟動,以虛擬機器A為例,相關的指令與輸出的訊息如下:
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~# systemctl restart clickhouse-server.service
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~# systemctl status clickhouse-server.service
● clickhouse-server.service - ClickHouse Server (analytic DBMS for big data)
Loaded: loaded (/lib/systemd/system/clickhouse-server.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-10-08 03:47:08 UTC; 16s ago
Main PID: 27981 (clckhouse-watch)
Tasks: 201 (limit: 4702)
CGroup: /system.slice/clickhouse-server.service
├─27981 clickhouse-watchdog --config=/etc/clickhouse-server/config.xml --pid-file=/run/clickhouse-server/clickhouse-server.pid
└─28008 /usr/bin/clickhouse-server --config=/etc/clickhouse-server/config.xml --pid-file=/run/clickhouse-server/clickhouse-server.pid
Oct 08 03:47:08 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Processing configuration file '/etc/clickhouse-server/config.xml'.
Oct 08 03:47:08 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Merging configuration file '/etc/clickhouse-server/config.d/listen_host.xml'.
Oct 08 03:47:08 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Logging trace to /var/log/clickhouse-server/clickhouse-server.log
Oct 08 03:47:08 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Logging errors to /var/log/clickhouse-server/clickhouse-server.err.log
Oct 08 03:47:09 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Processing configuration file '/etc/clickhouse-server/config.xml'.
Oct 08 03:47:09 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Merging configuration file '/etc/clickhouse-server/config.d/listen_host.xml'.
Oct 08 03:47:09 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Saved preprocessed configuration to '/var/lib/clickhouse/preprocessed_configs/config.xml'.
Oct 08 03:47:09 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Processing configuration file '/etc/clickhouse-server/users.xml'.
Oct 08 03:47:09 ubuntu-s-2vcpu-4gb-amd-sgp1-01 clickhouse-server[27981]: Merging configuration file '/etc/clickhouse-server/users.d/default-password.xml'.
執行完成上述的設定之後,可以試著使用clickhouse-client
指令來測試上述的設定是否正確。
下面指令是在虛擬機器A連到虛擬機器A並以該區域網路IP位址進行連線,相關指令的執行過程與輸出的訊息如下:
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# clickhouse-client --host 10.130.0.3 --password
ClickHouse client version 22.8.4.7 (official build).
Password for user (default):
Connecting to 10.130.0.3:9000 as user default.
Connected to ClickHouse server version 22.8.4 revision 54460.
Warnings:
* Linux is not using a fast TSC clock source. Performance can be degraded. Check /sys/devices/system/clocksource/clocksource0/current_clocksource
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) exit;
Bye.
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~#
下面的指令是在虛擬機器B連到虛擬機器B並以該區域網路IP位址進行連線,相關指令的執行過程與輸出的訊息如下:
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~# clickhouse-client --host 10.130.0.2 --password
ClickHouse client version 22.9.3.18 (official build).
Password for user (default):
Connecting to 10.130.0.2:9000 as user default.
Connected to ClickHouse server version 22.9.3 revision 54460.
Warnings:
* Maximum number of threads is lower than 30000. There could be problems with handling a lot of simultaneous queries.
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :) exit;
Bye.
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~#
接著分別在虛擬機器A與B都建立好shard
的資料庫,相關執行的指令與輸出的訊息如下:
# 在虛擬機器A上
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# clickhouse-client --password
ClickHouse client version 22.8.4.7 (official build).
Password for user (default):
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 22.8.4 revision 54460.
Warnings:
* Linux is not using a fast TSC clock source. Performance can be degraded. Check /sys/devices/system/clocksource/clocksource0/current_clocksource
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) CREATE DATABASE shard;
CREATE DATABASE shard
Query id: 488811f4-0e25-4495-a5a3-653e67f043bc
Ok.
0 rows in set. Elapsed: 0.007 sec.
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) exit;
Bye.
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~#
# 在虛擬機器B上
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~# clickhouse-client --password
ClickHouse client version 22.9.3.18 (official build).
Password for user (default):
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 22.9.3 revision 54460.
Warnings:
* Maximum number of threads is lower than 30000. There could be problems with handling a lot of simultaneous queries.
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :) CREATE DATABASE shard;
CREATE DATABASE shard
Query id: 52665969-e1d3-4f84-bb32-6648c0083838
Ok.
0 rows in set. Elapsed: 0.014 sec.
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :) exit;
Bye.
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~#
下列的設定範例是解釋如何設定一個叢集包含兩個節點,並在每個節點上有一個資料片段,因此我們在虛擬機器A與虛擬機器B上分別使用下列的設定:
<clickhouse>
<remote_servers>
<shard_cluster>
<shard>
<replica>
<default_database>shard</default_database>
<host>10.130.0.3</host>
<port>9000</port>
<password>password</password>
</replica>
</shard>
<shard>
<replica>
<default_database>shard</default_database>
<host>10.130.0.2</host>
<port>9000</port>
<password>password</password>
</replica>
</shard>
</shard_cluster>
</remote_servers>
</clickhouse>
接著將上述的設定分別設定到虛擬機器A與虛擬機器B上,相關執行指令如下:
# 在虛擬機器A上
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# vim /etc/clickhouse-server/config.d/shard.xml
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# cat /etc/clickhouse-server/config.d/shard.xml
<clickhouse>
<remote_servers>
<shard_cluster>
<shard>
<replica>
<default_database>shard</default_database>
<host>10.130.0.3</host>
<port>9000</port>
<password>password</password>
</replica>
</shard>
<shard>
<replica>
<default_database>shard</default_database>
<host>10.130.0.2</host>
<port>9000</port>
<password>password</password>
</replica>
</shard>
</shard_cluster>
</remote_servers>
</clickhouse>
# 在虛擬機器B上
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~# vim /etc/clickhouse-server/config.d/shard.xml
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~# cat /etc/clickhouse-server/config.d/shard.xml
<clickhouse>
<remote_servers>
<shard_cluster>
<shard>
<replica>
<default_database>shard</default_database>
<host>10.130.0.2</host>
<port>9000</port>
<password>password</password>
</replica>
</shard>
<shard>
<replica>
<default_database>shard</default_database>
<host>10.130.0.3</host>
<port>9000</port>
<password>password</password>
</replica>
</shard>
</shard_cluster>
</remote_servers>
</clickhouse>
上述設定完成後,記得在每個虛擬機器上執行下列的指令:
systemctl restart clickhouse-server.service
我們在兩個設定的節點上建立分片資料表,建立的分片資料表的SQL語句如下:
CREATE TABLE shard.test
(
id Int64,
event_time DateTime
)
Engine=MergeTree()
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id;
執行上述建立資料表的指令與輸出的訊息如下:
# 在虛擬機器A
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# clickhouse-client --password
ClickHouse client version 22.8.4.7 (official build).
Password for user (default):
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 22.8.4 revision 54460.
Warnings:
* Linux is not using a fast TSC clock source. Performance can be degraded. Check /sys/devices/system/clocksource/clocksource0/current_clocksource
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) CREATE TABLE shard.test
(
id Int64,
event_time DateTime
)
Engine=MergeTree()
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id;
CREATE TABLE shard.test
(
`id` Int64,
`event_time` DateTime
)
ENGINE = MergeTree
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id
Query id: b8844b16-8389-4070-b237-b5c9e919a895
Ok.
0 rows in set. Elapsed: 0.007 sec.
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) exit;
Bye.
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~#
# 在虛擬機器B
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~# clickhouse-client --password
ClickHouse client version 22.9.3.18 (official build).
Password for user (default):
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 22.9.3 revision 54460.
Warnings:
* Maximum number of threads is lower than 30000. There could be problems with handling a lot of simultaneous queries.
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :) CREATE TABLE shard.test
(
`id` Int64,
`event_time` DateTime
)
ENGINE = MergeTree
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id;
CREATE TABLE shard.test
(
`id` Int64,
`event_time` DateTime
)
ENGINE = MergeTree
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id
Query id: ee3c14da-03d2-4910-b452-de25cc33b0d0
Ok.
0 rows in set. Elapsed: 0.010 sec.
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :) exit;
Bye.
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~#
建立上述的資料表是用來維持資料,即分片的資料表(shard table)。
接著建立分散式的資料表,分散式的資料表通常是一個視圖(view),所以其資料表的綱要的定義要與上述分片的資料表相同,一旦此視圖建立了,在執行查詢時資料會從每個片段中進行讀取與查詢。
而且會在最初呼叫查詢的節點上進行聚合整理並輸出查詢的結果。
接著我們建立主要的資料表在虛擬機器A上,這個資料表將會用來作為所有人都可以存取,資料表綱要如下:
CREATE TABLE default.test_for_shard
(
`id` Int64,
`event_time` DateTime
)
ENGINE = Distributed('shard_cluster', '', test, rand())
上述的SQL語句中可以知道,在Distributed
的第二個參數是綱要名稱,如果是空白的話,則會使用先前設定在伺服器上的預設資料庫的設定值,我們設定是shard
,因此就會使用shard當作預設資料庫。
在虛擬機器A上透過clickhouse-client
執行上述的SQL語句所輸出的訊息如下:
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) CREATE TABLE default.test_for_shard
(
id Int64,
event_time DateTime
)
ENGINE = Distributed('shard_cluster', '', test, rand());
CREATE TABLE default.test_for_shard
(
`id` Int64,
`event_time` DateTime
)
ENGINE = Distributed('shard_cluster', '', test, rand())
Query id: ea30aba3-346a-4c00-a359-b0446e0247bb
Ok.
0 rows in set. Elapsed: 0.006 sec.
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :)
接著測試將一些資料寫入到default.test_for_shard
之資料表中,使用下列的SQL語句:
INSERT INTO default.test_for_shard VALUES (1, now()) (2, now()), (3, now());
執行上述的SQL語句所輸出的訊息如下:
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) INSERT INTO default.test_for_shard VALUES (1, now()) (2, now()), (3, now());
INSERT INTO default.test_for_shard FORMAT Values
Query id: 9efb3c37-82bd-4a2a-bc2e-f1a8ab014968
Ok.
3 rows in set. Elapsed: 0.002 sec.
對default.test_for_shard
之資料表進行篩選,相關SQL語句透過clickhouse-client
執行所輸出的訊息如下:
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) SELECT * FROM default.test_for_shard;
SELECT *
FROM default.test_for_shard
Query id: df0d9cf0-c924-4028-9604-5211f48b75aa
┌─id─┬──────────event_time─┐
│ 1 │ 2022-10-08 04:47:14 │
└────┴─────────────────────┘
┌─id─┬──────────event_time─┐
│ 2 │ 2022-10-08 04:47:14 │
│ 3 │ 2022-10-08 04:47:14 │
└────┴─────────────────────┘
3 rows in set. Elapsed: 0.008 sec.
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :)
會得到上述的查詢結果是因為資料存放在在不同的片段資料表中,並查詢出來之後聚合成一張資料表的結果並輸出出出來。
從上述的章節我們知道如何設定從多個節點中讀取資料出來,為了對節點有容錯的功能特性,且我們想要確定我們的資料是有複製的,因此需要設定資料複製(Data replication)。
為了達到資料複製的功能,我們需要下列的事項:
ReplicatedMergeTree
作為建立資料表的引擎。首先須先安裝好zookeeper
套件,分別在節點上進行安裝,因此在虛擬機器A與虛擬機器B上進行安裝,下列以虛擬機器A為例,並可以執行下列的指令完成:
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# apt-get install zookeeper
安裝好zookeeper套件後,建立zookeeper.service
的檔案描述ZooKeeper的背景啟動服務:
[Unit]
Description=Zookeeper Daemon
Documentation=http://zookeeper.apache.org
Requires=network.target
After=network.target
[Service]
Type=forking
WorkingDirectory=/usr/share/zookeeper
User=zookeeper
Group=zookeeper
ExecStart=/usr/share/zookeeper/bin/zkServer.sh start
ExecStop=/usr/share/zookeeper/bin/zkServer.sh stop
ExecReload=/usr/share/zookeeper/bin/zkServer.sh restart
TimeoutSec=30
Restart=on-failure
[Install]
WantedBy=default.target
將上述的檔案複製到/etc/systemd/system
之目錄底下,執行上述的指令如下:
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# cp zookeeper.service /etc/systemd/system/
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# cat zookeeper.service
[Unit]
Description=Zookeeper Daemon
Documentation=http://zookeeper.apache.org
Requires=network.target
After=network.target
[Service]
Type=forking
WorkingDirectory=/usr/share/zookeeper
User=zookeeper
Group=zookeeper
ExecStart=/usr/share/zookeeper/bin/zkServer.sh start
ExecStop=/usr/share/zookeeper/bin/zkServer.sh stop
ExecReload=/usr/share/zookeeper/bin/zkServer.sh restart
TimeoutSec=30
Restart=on-failure
[Install]
WantedBy=default.target
接著執行systemctl daemon-reload
讓systemctl
指令重新載入,接著就可以透過systemctl
控制ZooKeeper服務了,相關執行指令與輸出的訊息如下:
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# systemctl enable --now zookeeper.service
Created symlink /etc/systemd/system/default.target.wants/zookeeper.service → /etc/systemd/system/zookeeper.service.
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# systemctl status zookeeper.service
● zookeeper.service - Zookeeper Daemon
Loaded: loaded (/etc/systemd/system/zookeeper.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-10-08 05:28:47 UTC; 18s ago
Docs: http://zookeeper.apache.org
Process: 2380 ExecStart=/usr/share/zookeeper/bin/zkServer.sh start (code=exited, status=0/SUCCESS)
Main PID: 2400 (java)
Tasks: 22 (limit: 4915)
CGroup: /system.slice/zookeeper.service
└─2400 /usr/bin/java -Dzookeeper.log.dir=/var/log/zookeeper -Dzookeeper.root.logger=INFO,ROLLINGFILE -cp /etc/zookeeper/conf:/usr/share/java/jline.jar:/usr/share/java/log4j-1.2.
Oct 08 05:28:46 ubuntu-s-4vcpu-8gb-amd-sgp1-01 systemd[1]: Starting Zookeeper Daemon...
Oct 08 05:28:46 ubuntu-s-4vcpu-8gb-amd-sgp1-01 zkServer.sh[2380]: ZooKeeper JMX enabled by default
Oct 08 05:28:46 ubuntu-s-4vcpu-8gb-amd-sgp1-01 zkServer.sh[2380]: Using config: /etc/zookeeper/conf/zoo.cfg
Oct 08 05:28:47 ubuntu-s-4vcpu-8gb-amd-sgp1-01 zkServer.sh[2380]: Starting zookeeper ... STARTED
Oct 08 05:28:47 ubuntu-s-4vcpu-8gb-amd-sgp1-01 systemd[1]: Started Zookeeper Daemon.
從上述的指令可以知道,我們使用了enable
並搭配--now
參數將ZooKeeper的服務啟動並設定開機時自動啟動該服務。
當虛擬機器A與虛擬機器B都安裝並啟動好ZooKeeper之後,分別在各節點的資料庫伺服器上設定下列的設定:
<clickhouse>
<zookeeper>
<node index="1">
<host>10.130.0.3</host>
<port>2181</port>
</node>
<node index="2">
<host>10.130.0.2</host>
<port>2181</port>
</node>
</zookeeper>
</clickhouse>
編輯設定檔案的指令如下:
vim /etc/clickhouse-server/config.d/zookeeper.xml
在虛擬機器A與B都設定好之後,接著重新啟動ClickHouse資料庫伺服器之背景服務,要注意的是上述的ZooKeeper服務要確保在兩台機器上都已經有啟動了,才可以對ClickHouse資料庫伺服器進行重新啟動。
相關重新啟動資料庫伺服器的服務指令如下:
systemctl restart clickhouse-server.service
資料複製需要使用ReplicatedMergeTree的資料表引擎完成,ReplicatedMergeTree之參數為zookeeper_path
與replica_name
,資料表需要設定相同的zookeeper_path
這樣資料才會持續的同步。
Zookeeper的路徑可以是任意的字串,只要是符合的相同路徑字串就會進行資料複製與同步。
為了要簡單化,我們應該要建立標準化字串定義。舉例來說,使用/clickhouse/tables/<main_replica_host>/<table_name>
的格式進行設定。
在前面小章節中,我們討論有關於如何在不論是在多個節點上存取資料,或是進行資料複製。在這個小章節中,我們將會展示將分散資料與資料複製和在一起進行設定並得到具有分散且複製資料的叢集。
為了達到這樣的目的,需要注意下列的事項:
default
的資料庫中所建立的資料表使用的是Distributed
作為該資料表引擎。shard
的資料庫中所建立的資料表使用的是ReplicatedMergeTree
作為資料表引擎所儲存主要的資料的地方。replica
的資料庫中所建立的資料表使用的是ReplicatedMergeTree
作為資料表引擎所儲存從另一個伺服器的shard
資料庫中的資料表複製而來的資料,例如:虛擬機器A複製資料將會儲存到虛擬機器B。首先先將虛擬機器A與B的/etc/clickhouse-server/config.d/shard.xml
檔案進行編輯,編輯成下列的檔案:
<clickhouse>
<remote_servers>
<shard_cluster>
<shard>
<replica>
<default_database>shard</default_database>
<host>10.130.0.3</host>
<port>9000</port>
<password>password</password>
</replica>
<replica>
<default_database>replica</default_database>
<host>10.130.0.2</host>
<port>9000</port>
<password>password</password>
</replica>
</shard>
<shard>
<replica>
<default_database>shard</default_database>
<host>10.130.0.2</host>
<port>9000</port>
<password>password</password>
</replica>
<replica>
<default_database>replica</default_database>
<host>10.130.0.3</host>
<port>9000</port>
<password>password</password>
</replica>
</shard>
</shard_cluster>
</remote_servers>
</clickhouse>
接著我們在虛擬機器A上執行下列的SQL語句:
DROP DATABASE shard;
CREATE DATABASE shard;
CREATE DATABASE replica;
CREATE TABLE shard.test
(
`id` Int64,
`event_time` DateTime
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/shard1/test', 'replica_1')
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id;
CREATE TABLE replica.test
(
`id` Int64,
`event_time` DateTime
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/shard2/test', 'replica_2')
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id;
CREATE TABLE default.test_for_replica
(
`id` Int64,
`event_time` DateTime
)
ENGINE = Distributed('shard_cluster', '', test, rand());
接著我們在虛擬機器B上執行下列的SQL語句:
DROP DATABASE shard;
CREATE DATABASE shard;
CREATE DATABASE replica;
CREATE TABLE shard.test
(
`id` Int64,
`event_time` DateTime
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/shard2/test', 'replica_1')
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id;
CREATE TABLE replica.test
(
`id` Int64,
`event_time` DateTime
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/shard1/test', 'replica_2')
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id;
CREATE TABLE default.test_for_replica
(
`id` Int64,
`event_time` DateTime
)
ENGINE = Distributed('shard_cluster', '', test, rand());
上述的SQL語句都在虛擬機器A與B執行完成後,可以知道相關的事項如下:
shard.test
資料表資料會複製到虛擬機器B的replica.test
資料表上。shard.test
資料表資料會複製到虛擬機器A的replica.test
資料表上。接著在虛擬機器A上的default.test_for_replica
的資料表執行下列的SQL語句:
INSERT INTO test_for_replica VALUES(1, now()) (2, now()) (3, now());
執行完成後,執行下列的SQL語句以及可以看到輸出的結果如下:
-- 在虛擬機器A執行
SELECT * FROM replica.test;
SELECT *
FROM replica.test
Query id: 2c91d410-ee75-4c41-b0c8-b65d102bbeea
┌─id─┬──────────event_time─┐
│ 1 │ 2022-10-08 07:24:37 │
│ 3 │ 2022-10-08 07:24:37 │
└────┴─────────────────────┘
-- 在虛擬機器A執行
SELECT * FROM shard.test;
SELECT *
FROM shard.test
Query id: 219a7aef-64c7-498a-a8f3-580c4b10bfd5
┌─id─┬──────────event_time─┐
│ 2 │ 2022-10-08 07:24:37 │
└────┴─────────────────────┘
-- 在虛擬機器B執行
SELECT * FROM shard.test;
SELECT *
FROM shard.test
Query id: b4d3ece8-42a0-443c-b9e3-981957b40a96
┌─id─┬──────────event_time─┐
│ 1 │ 2022-10-08 07:24:37 │
│ 3 │ 2022-10-08 07:24:37 │
└────┴─────────────────────┘
2 rows in set. Elapsed: 0.003 sec.
-- 在虛擬機器B執行
SELECT * FROM replica.test;
SELECT *
FROM replica.test
Query id: e7ced29e-a61c-44fb-9eac-4f76856d9f45
┌─id─┬──────────event_time─┐
│ 2 │ 2022-10-08 07:24:37 │
└────┴─────────────────────┘
需要注意的是,我們也可以在第一個主要節點上指定分片的資料表進行資料寫入,相關範例如下:
-- 在虛擬機器A執行
INSERT INTO shard.test VALUES(4, now()) (5, now()) (6, now());
接著對default.test_replica
之資料表進行查詢:
-- 在虛擬機器A執行
SELECT * FROM default.test_for_replica;
-- 上上執行後會得到的結果為
-- ┌─id─┬──────────event_time─┐
-- │ 1 │ 2022-10-08 13:16:32 │
-- └────┴─────────────────────┘
-- ┌─id─┬──────────event_time─┐
-- │ 4 │ 2022-10-08 13:22:01 │
-- │ 5 │ 2022-10-08 13:22:01 │
-- │ 6 │ 2022-10-08 13:22:01 │
-- └────┴─────────────────────┘
-- ┌─id─┬──────────event_time─┐
-- │ 2 │ 2022-10-08 13:16:32 │
-- │ 3 │ 2022-10-08 13:16:32 │
-- └────┴─────────────────────┘
-- 得結果的排序是隨機的,原因是從不同的資料分片中取出來的。
當ZooKeeper中設定的兩個節點,當第二個節點有問題的時候,則所有的分片或是複製資料表皆會變成唯讀模式,即無法再寫入資料,相關操作的情形如下:
# 在虛擬機器B(即第二個節點)執行poweroff指令將此機器關機
root@ubuntu-s-2vcpu-4gb-amd-sgp1-01:~# poweroff
Connection to 157.230.252.205 closed by remote host.
Connection to 157.230.252.205 closed.
# 在虛擬機器A(即第一個節點)使用clickhouse-client連上資料庫並執行查詢
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) SELECT * FROM default.test_for_replica;
SELECT *
FROM default.test_for_replica
Query id: 9601141c-724e-4b5e-9be9-6a0efd887936
┌─id─┬──────────event_time─┐
│ 2 │ 2022-10-08 13:16:32 │
│ 3 │ 2022-10-08 13:16:32 │
└────┴─────────────────────┘
┌─id─┬──────────event_time─┐
│ 1 │ 2022-10-08 13:16:32 │
└────┴─────────────────────┘
┌─id─┬──────────event_time─┐
│ 4 │ 2022-10-08 13:22:01 │
│ 5 │ 2022-10-08 13:22:01 │
│ 6 │ 2022-10-08 13:22:01 │
└────┴─────────────────────┘
6 rows in set. Elapsed: 0.274 sec.
# 在虛擬機器A嘗試要寫入新的資料,則會出現下列的錯誤
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :) INSERT INTO shard.test VALUES(7, now()) (8, now()) (9, now());
INSERT INTO shard.test FORMAT Values
Query id: 120f63ff-b9c9-487c-84d7-8420ae068016
0 rows in set. Elapsed: 0.002 sec.
Received exception from server (version 22.8.4):
Code: 242. DB::Exception: Received from localhost:9000. DB::Exception: Table is in readonly mode (replica path: /clickhouse/tables/shard1/test/replicas/replica_1). (TABLE_IS_READ_ONLY)
ubuntu-s-4vcpu-8gb-amd-sgp1-01 :)
若是主要節點,即設定索引的第一個節點的虛擬機器A關機的話,則虛擬機器B的設定的資料片段與複製資料表進入唯讀模式,而設定Distributed資料表引擎的資料表也可以查詢出資料,相關執行指令與輸出的訊息如下:
# 在虛擬機器B執行下列的SQL查詢
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :) SELECT * FROM default.test_for_replica;
SELECT *
FROM default.test_for_replica
Query id: 7ddf09a6-c71f-4093-a3da-1599f3b0d780
┌─id─┬──────────event_time─┐
│ 2 │ 2022-10-08 13:16:32 │
│ 3 │ 2022-10-08 13:16:32 │
└────┴─────────────────────┘
┌─id─┬──────────event_time─┐
│ 1 │ 2022-10-08 13:16:32 │
└────┴─────────────────────┘
┌─id─┬──────────event_time─┐
│ 4 │ 2022-10-08 13:22:01 │
│ 5 │ 2022-10-08 13:22:01 │
│ 6 │ 2022-10-08 13:22:01 │
└────┴─────────────────────┘
# 在虛擬機器A執行poweroff指令關機
root@ubuntu-s-4vcpu-8gb-amd-sgp1-01:~# poweroff
Connection to 128.199.192.154 closed by remote host.
Connection to 128.199.192.154 closed.
# 在虛擬機器B再次執行上述的SQL查詢
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :) SELECT * FROM default.test_for_replica;
SELECT *
FROM default.test_for_replica
Query id: 7ddf09a6-c71f-4093-a3da-1599f3b0d780
┌─id─┬──────────event_time─┐
│ 2 │ 2022-10-08 13:16:32 │
│ 3 │ 2022-10-08 13:16:32 │
└────┴─────────────────────┘
┌─id─┬──────────event_time─┐
│ 1 │ 2022-10-08 13:16:32 │
└────┴─────────────────────┘
┌─id─┬──────────event_time─┐
│ 4 │ 2022-10-08 13:22:01 │
│ 5 │ 2022-10-08 13:22:01 │
│ 6 │ 2022-10-08 13:22:01 │
└────┴─────────────────────┘
# 在虛擬機器B執行寫入資料SQL語句
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :) INSERT INTO shard.test VALUES(7, now()) (8, now()) (9, now());
INSERT INTO shard.test FORMAT Values
Query id: 60552d92-2755-4789-8e43-6ad7ea6045ed
0 rows in set. Elapsed: 0.001 sec.
Received exception from server (version 22.9.3):
Code: 242. DB::Exception: Received from localhost:9000. DB::Exception: Table is in readonly mode (replica path: /clickhouse/tables/shard2/test/replicas/replica_1). (TABLE_IS_READ_ONLY)
ubuntu-s-2vcpu-4gb-amd-sgp1-01 :)
從本章節可以知道,如何設定一個叢集以及搭配ZooKeeper進行節點的監控,以及設定資料分片讓資料可以分布在各個設定的資料節點中,同時也使用了資料複製的功能,將資料分片的資料都有一份複製。
因此當否個節點因為否些原因停機或是出問題的時候,則可以健康的節點仍保有完整的資料,以兩個節點來說,每個節點都有一部分的資料分片以及另一份資料分片的副本,即為一份完整的資料集。