18_clickhouse副本同步与高可用功能验证,分布式表与集群配置,数据副本与复制表,ZooKeeper整合,创建复制表,副本同步机制,数据原子写入与去重,负载平衡策略,案例(学习笔记)
24.副本同步與高可用功能驗(yàn)證
24.1.分布式表與集群配置
24.2.數(shù)據(jù)副本與復(fù)制表
24.3.ZooKeeper整合
24.4.創(chuàng)建復(fù)制表
24.5.副本同步機(jī)制
24.6.數(shù)據(jù)原子寫入與去重
24.7.負(fù)載平衡策略
24.8.案例
24.副本同步與高可用功能驗(yàn)證
此部分,上接:https://blog.csdn.net/tototuzuoquan/article/details/111027342
24.1.分布式表與集群配置
分布式表基于Distributed引擎創(chuàng)建,在多個(gè)分片上運(yùn)行分布式查詢。
讀取是自動(dòng)并行化的,可使用遠(yuǎn)程服務(wù)器上的索引(如果有)。
數(shù)據(jù)在請(qǐng)求的本地服務(wù)器上盡可能地被部分處理。例如,對(duì)于GROUP BY查詢,數(shù)據(jù)將在遠(yuǎn)程服務(wù)器 上聚合,聚合函數(shù)的中間狀態(tài)將發(fā)送到請(qǐng)求服務(wù)器,然后數(shù)據(jù)將進(jìn)一步聚合。
創(chuàng)建分布式表:
ENGINE = Distributed(cluster_name, db_name, table_name[, sharding_key[, policy_name]])參數(shù):
cluster_name:集群名稱。
db_name:數(shù)據(jù)庫(kù)名稱,可使用常量表達(dá)式:currentDatabase()。
table_name: 各分片上的表名稱。
sharding_key: (可選)分片的key,可設(shè)置為rand()。
policy_name: (可選)策略名稱,用于存儲(chǔ)異步發(fā)送的臨時(shí)文件。
例如下面的/etc/metrika.xml的一部分內(nèi)容:
<remote_servers><logs><shard><weight>1</weight><internal_replication>false</internal_replication><replica><host>example01-01-1</host><port>9000</port></replica><replica><host>example01-01-2</host><port>9000</port></replica></shard><shard><weight>2</weight><internal_replication>false</internal_replication><replica><host>example01-02-1</host><port>9000</port></replica><replica><host>example01-02-2</host><secure>1</secure><port>9000</port></replica></shard></logs> </remote_servers>這里定義了一個(gè)名為logs的集群名稱,它有兩個(gè)分片(shard)組成,每個(gè)分片包含兩個(gè)副本(replica)。
分片是包含數(shù)據(jù)的不同服務(wù)器(要讀取所有數(shù)據(jù),必須訪問所有分片)。
副本是存儲(chǔ)復(fù)制數(shù)據(jù)的服務(wù)器(要讀取所有數(shù)據(jù),訪問該分片上的任意一個(gè)副本上的數(shù)據(jù)即可)。
1.weight : 可選,寫入數(shù)據(jù)時(shí)分片的權(quán)重,建議忽略該配置。
2.internal_repliacation : 可選,同一時(shí)刻是否只將數(shù)據(jù)寫入其中一個(gè)副本。默認(rèn)值:false(將數(shù)據(jù)寫入所有副本),建議設(shè)置為true。寫一個(gè)即可。避免重復(fù)寫。
3.副本配置:配置每個(gè)Server的信息,必須參數(shù):host和port,可選參數(shù):user、password、secure和compression。
(1)、host : 遠(yuǎn)程服務(wù)器地址。支持IPv4和IPv6。也可指定域名,更改域名解析需 重啟服務(wù)。
(2)、port : 消息傳遞的TCP端口。配置文件的tcp_port指定的端口,通常設(shè)置為 9000。
(3)、user : 用于連接到服務(wù)的用戶名稱。默認(rèn)值:true。在users.xml文件中配置 了訪問權(quán)限。
(4)、password:用于連接到遠(yuǎn)程服務(wù)的密碼。默認(rèn)值:空字符串。
(5)、secure : 使用ssl進(jìn)行連接,通常還應(yīng)該定義port=9440。
(6)、compression : 使用數(shù)據(jù)壓縮。默認(rèn)值:true。
24.2.數(shù)據(jù)副本與復(fù)制表
只有MergeTree系列引擎支持?jǐn)?shù)據(jù)副本,支持副本的引擎是在MergeTree引擎名稱的前面加上前綴 Replicated。
副本是表級(jí)別的而不是整個(gè)服務(wù)器級(jí)別的,因此服務(wù)器可以同時(shí)存儲(chǔ)復(fù)制表和非復(fù)制表。
副本不依賴于分片,每個(gè)分片都有自己獨(dú)立的副本。
副本表如:
ReplicatedMergeTree ReplicatedSummingMergeTree ReplicatedReplacingMergeTree ReplicatedAggregatingMergeTree ReplicatedCollapsingMergeTree ReplicatedVersionedCollapsingMergeTree ReplicatedGraphiteMergeTree24.3.ZooKeeper整合
ClickHouse使用Apache ZooKeeper來存儲(chǔ)副本元信息, 在配置文件設(shè)置 zookeeper相關(guān)的參數(shù)。
ClickHouse在創(chuàng)建復(fù)制表的時(shí)候指定Zookeeper的目錄,指定的目錄會(huì)在建 表時(shí)自動(dòng)創(chuàng)建。
如果ClickHouse的配置文件未配置ZooKeeper, 則無法創(chuàng)建復(fù)制表, 并且 任何存量的復(fù)制表都將是只讀的。
對(duì)本地復(fù)制表的查詢,不會(huì)使用ZooKeeper, 其查詢速度和非復(fù)制表一樣快。
本地復(fù)制表的數(shù)據(jù)插入,針對(duì)每個(gè)數(shù)據(jù)塊(一個(gè)塊最多有 max_insert_block_size = 1048576條記錄),會(huì)通過幾個(gè)事務(wù)將大約十個(gè)條目添加到Zookeeper。因此,與非復(fù)制表相比, 復(fù)制表的INSERT操作等 待時(shí)間稍長(zhǎng)。
<zookeeper><node index="1"><host>example1</host><port>2181</port></node><node index="2"><host>example2</host><port>2181</port></node><node index="3"><host>example3</host><port>2181</port></node> </zookeeper>24.4.創(chuàng)建復(fù)制表
復(fù)制表的引擎要以Replicated為前綴,例如:ReplicatedMergeTree。
CREATE TABLE table_name (EventDate DateTime,CounterID UInt32,UserID UInt32 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/table_name', '{replica}') PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID);引擎參數(shù)包含了變量,這些變量是在配置文件的”macros”部分配置的,例如:
<macros><layers>05</layers><shard>02</shard><replica>clickhouse1</replica> </macros>Replicated*MergeTree引擎參數(shù):
?zoo_path : ZooKeeper中表的路徑。
?replica_name : ZooKeeper中的副本名稱。
1.第一個(gè)參數(shù)ZooKeeper路徑組成:
(1)、通用前綴:/clickhouse/tables/,建議復(fù)制表都使用類似這樣的前綴。
(2)、分片標(biāo)識(shí)符:{layer}-{shard},在本示例中,分片標(biāo)識(shí)符有兩部分組成,只要保證分片標(biāo)識(shí)符能唯一標(biāo)識(shí)一個(gè)分片即可。
(3)、ZooKeeper節(jié)點(diǎn)名稱:table_name。節(jié)點(diǎn)名稱最好與表名相同,節(jié)點(diǎn)名稱在定義后不會(huì)更改,即使執(zhí)行表的重命名操作。
2.第二個(gè)參數(shù)是副本名稱,用于標(biāo)識(shí)同一個(gè)分片的不同副本。副本名稱只需要在每個(gè)shard中唯一即可。
上面的示例中,復(fù)制引擎的參數(shù)使用了變量替換。ClickHouse也支持使用顯示的參數(shù)。在這種情況下,不能使用分布式的DDL查詢(ON CLUSTER)。建議使用變量替換的方式傳入?yún)?shù),降低出錯(cuò)概率。
在每個(gè)副本服務(wù)器上運(yùn)行CREATE TABLE語句,如果該分片的表在其他節(jié)點(diǎn)已經(jīng)創(chuàng)建且有數(shù)據(jù),則該新副本自動(dòng)同步其他副本的數(shù)據(jù)。
24.5.副本同步機(jī)制
復(fù)制是多主異步的。
INSERT語句(以及ALTER)可在任意可用的服務(wù)器上執(zhí)行。數(shù)據(jù)首先插入到本地的服務(wù)器 (即運(yùn)行查詢的服務(wù)器),然后數(shù)據(jù)被復(fù)制到其他服務(wù)器。
由于復(fù)制是異步的,所以最近插入的數(shù)據(jù)出現(xiàn)在其他副本上會(huì)有一定的延遲。
如果部分副本不可用,則在它們可用時(shí)寫入數(shù)據(jù)。
如果副本可用, 則等待的時(shí)間是通過網(wǎng)絡(luò)傳輸壓縮數(shù)據(jù)塊所耗費(fèi)的時(shí)間。
默認(rèn)情況下, INSERT操作只需等待一個(gè)副本寫入成功后返回。如果僅將數(shù)據(jù)成功寫入一個(gè) 副本,并且該副本的服務(wù)器不再存在, 則存儲(chǔ)的數(shù)據(jù)將丟失。要啟動(dòng)來自多個(gè)副本的寫入確 認(rèn)機(jī)制,使用insert_quorum選項(xiàng)。
24.6.數(shù)據(jù)原子寫入與去重
INSERT查詢按照數(shù)據(jù)塊插入數(shù)據(jù),每個(gè)數(shù)據(jù)塊最多max_insert_block_size(默認(rèn) max_insert_block_size = 1048576)條記錄。換言之, 如果INSERT插入少于1048576條記 錄,則插入操作是原子的。單個(gè)數(shù)據(jù)塊的寫入是原子的。
數(shù)據(jù)塊是去重的。 對(duì)于同一數(shù)據(jù)塊的多次寫入(相同大小的的數(shù)據(jù)塊,包含相同的行以及相 同的順序),該塊僅寫入一次。在出現(xiàn)網(wǎng)口故障等異常情況下, 客戶端應(yīng)用程序不知道數(shù)據(jù) 是否已將數(shù)據(jù)成功寫入數(shù)據(jù)庫(kù),因此可以簡(jiǎn)單地重復(fù)執(zhí)行INSERT查詢。相同的數(shù)據(jù)發(fā)送到哪 個(gè)副本進(jìn)行插入并不重要,INSERT是冪等的。數(shù)據(jù)去重可通過參數(shù) insert_deduplicate控 制,默認(rèn)為0(開啟去重)。
在復(fù)制過程中, 只有插入的源數(shù)據(jù)通過網(wǎng)絡(luò)傳輸。進(jìn)一步的數(shù)據(jù)轉(zhuǎn)換(合并)會(huì)在所有副本 上以相同的方式進(jìn)行處理。 這樣可以最大限度減少網(wǎng)絡(luò)帶寬占用,這意味著當(dāng)副本位于不同 的數(shù)據(jù)中心時(shí),復(fù)制的效果也很好。
ClickHouse內(nèi)部監(jiān)控副本的數(shù)據(jù)同步,并能夠在發(fā)生故障后恢復(fù)。故障轉(zhuǎn)義是自動(dòng)的(對(duì)于數(shù)據(jù)的微小差異)或半自動(dòng)的(當(dāng)數(shù)據(jù)的差異太大時(shí),這可能表示配置錯(cuò)誤)。
ClickHouse內(nèi)部監(jiān)控副本上的數(shù)據(jù)同步,并能夠在發(fā)生故障后恢復(fù)。故障轉(zhuǎn)移是自動(dòng)的(對(duì)于數(shù)據(jù)的微小差異)或半自動(dòng)的(當(dāng)數(shù)據(jù)差異太大時(shí),這可能表示配置錯(cuò)誤)。
24.7.負(fù)載平衡策略
執(zhí)行分布式查詢時(shí),首先計(jì)算分片的每個(gè)副本的錯(cuò)誤數(shù),然后將查詢發(fā)送至最少錯(cuò)誤的副本。如果沒有錯(cuò)誤或者錯(cuò)誤數(shù)相同,則按如下的策略查詢數(shù)據(jù):
1.random(默認(rèn)) : 將查詢發(fā)送至任意一個(gè)副本。
2.nearest_hostname : 將查詢發(fā)送至主機(jī)名最相似的副本。
3.in_order : 將查詢按配置文件中的配置順序發(fā)送至副本。
4.first_or_random : 選擇第一個(gè)副本,如果第一個(gè)副本不可用,隨機(jī)選擇一個(gè)可用的副本。
設(shè)置策略的方式:
24.8.案例
1.在所有節(jié)點(diǎn)執(zhí)行如下語句:
創(chuàng)建本地復(fù)制表:
執(zhí)行效果圖:
在clickhouse1節(jié)點(diǎn)執(zhí)行的效果圖如下:
在clickhouse2-4上執(zhí)行后的效果如下(提示已經(jīng)存在了):
clickhouse2 :) CREATE TABLE table_local on cluster mycluster :-] (EventDate DateTime, :-] CounterID UInt32, :-] UserID UInt32 :-] ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/table_local', '{replica}') :-] PARTITION BY toYYYYMM(EventDate) :-] ORDER BY (CounterID, EventDate, intHash32(UserID)) :-] SAMPLE BY intHash32(UserID);CREATE TABLE table_local ON CLUSTER mycluster (`EventDate` DateTime,`CounterID` UInt32,`UserID` UInt32 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/table_local', '{replica}') PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID)┌─host────────────┬─port─┬─status─┬─error─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─num_hosts_remaining─┬─num_hosts_active─┐ │ 192.168.106.103 │ 9000 │ 57 │ Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build)) │ 3 │ 2 │ └─────────────────┴──────┴────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────┴──────────────────┘ ┌─host────────────┬─port─┬─status─┬─error─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─num_hosts_remaining─┬─num_hosts_active─┐ │ 192.168.106.104 │ 9000 │ 57 │ Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build)) │ 2 │ 0 │ │ 192.168.106.105 │ 9000 │ 57 │ Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build)) │ 1 │ 0 │ │ 192.168.106.106 │ 9000 │ 57 │ Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build)) │ 0 │ 0 │ └─────────────────┴──────┴────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────┴──────────────────┘ ← Progress: 4.00 rows, 720.00 B (26.16 rows/s., 4.71 KB/s.) 99% Received exception from server (version 20.9.3): Code: 57. DB::Exception: Received from localhost:9000. DB::Exception: There was an error on [192.168.106.103:9000]: Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build)). 4 rows in set. Elapsed: 0.154 sec. clickhouse2 :)通過上面的案例可以知道,只要在一個(gè)節(jié)點(diǎn)上創(chuàng)建了副本表之后,在其它節(jié)點(diǎn)上也已經(jīng)存在了。
創(chuàng)建分布式表:
CREATE TABLE table_distributed as table_local ENGINE = Distributed(mycluster, default, table_local, rand());(1)、驗(yàn)證副本的復(fù)制
在clickhouse1上,對(duì)本地表操作。
在clickhouse2上(clickhouse1的分片副本節(jié)點(diǎn))上,驗(yàn)證數(shù)據(jù)是否同步:
clickhouse2 :) select * from table_local;SELECT * FROM table_local┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:33 │ 22 │ 37 │ └─────────────────────┴───────────┴────────┘1 rows in set. Elapsed: 0.019 sec. clickhouse2 :)在clickhouse3-4上執(zhí)行(即shard2上)。發(fā)現(xiàn)查詢不到結(jié)果,效果如下:
clickhouse3 :) select * from table_local;SELECT * FROM table_localOk.0 rows in set. Elapsed: 0.005 sec. clickhouse3 :) clickhouse4 :) select * from table_local;SELECT * FROM table_localOk.0 rows in set. Elapsed: 0.005 sec. clickhouse4 :)(3)、驗(yàn)證集群的功能
在任意節(jié)點(diǎn)查看分布式表的數(shù)據(jù)(都將出現(xiàn)下面的效果)。
在任意一個(gè)節(jié)點(diǎn)往分布式表里面插入5條數(shù)據(jù):
insert into table_distributed values('2020-03-11 12:12:31', 21, 1); clickhouse4上執(zhí)行 insert into table_distributed values('2020-03-12 12:12:32', 22, 2); clickhouse4上執(zhí)行 insert into table_distributed values('2020-03-13 12:12:33', 23, 3); clickhouse3上執(zhí)行 insert into table_distributed values('2020-03-14 12:12:34', 24, 4); clickhouse3上執(zhí)行 insert into table_distributed values('2020-03-15 12:12:35', 25, 5); clickhouse2上執(zhí)行然后在任意一臺(tái)機(jī)器上執(zhí)行:
select * from table_distributed;都可以看到:
clickhouse1 :) select * from table_distributed;SELECT * FROM table_distributed┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:33 │ 22 │ 37 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-12 12:12:32 │ 22 │ 2 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-14 12:12:34 │ 24 │ 4 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-15 12:12:35 │ 25 │ 5 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:31 │ 21 │ 1 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-13 12:12:33 │ 23 │ 3 │ └─────────────────────┴───────────┴────────┘6 rows in set. Elapsed: 0.009 sec. clickhouse1 :)然后,分別在兩個(gè)分片的主機(jī)上查詢本地表:
在clickhouse1-2上(shard1)發(fā)現(xiàn)的效果是:
在clickhouse3-4上(shard2)發(fā)現(xiàn)的效果是:
clickhouse3 :) select * from table_local;SELECT * FROM table_local┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:31 │ 21 │ 1 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-13 12:12:33 │ 23 │ 3 │ └─────────────────────┴───────────┴────────┘2 rows in set. Elapsed: 0.002 sec. clickhouse3 :)可以看到,使用分布式表插入數(shù)據(jù),數(shù)據(jù)分散到不同分片(shard)的本地表。
總結(jié)
以上是生活随笔為你收集整理的18_clickhouse副本同步与高可用功能验证,分布式表与集群配置,数据副本与复制表,ZooKeeper整合,创建复制表,副本同步机制,数据原子写入与去重,负载平衡策略,案例(学习笔记)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 01_ClickHouse概述,速度,分
- 下一篇: 五菱宏光的车门子锁住了为什么还能打?