日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

18_clickhouse副本同步与高可用功能验证,分布式表与集群配置,数据副本与复制表,ZooKeeper整合,创建复制表,副本同步机制,数据原子写入与去重,负载平衡策略,案例(学习笔记)

發布時間:2024/9/27 编程问答 31 豆豆

24.副本同步與高可用功能驗證
24.1.分布式表與集群配置
24.2.數據副本與復制表
24.3.ZooKeeper整合
24.4.創建復制表
24.5.副本同步機制
24.6.數據原子寫入與去重
24.7.負載平衡策略
24.8.案例

24.副本同步與高可用功能驗證

此部分,上接:https://blog.csdn.net/tototuzuoquan/article/details/111027342

24.1.分布式表與集群配置

分布式表基于Distributed引擎創建,在多個分片上運行分布式查詢。
讀取是自動并行化的,可使用遠程服務器上的索引(如果有)。
數據在請求的本地服務器上盡可能地被部分處理。例如,對于GROUP BY查詢,數據將在遠程服務器 上聚合,聚合函數的中間狀態將發送到請求服務器,然后數據將進一步聚合。

創建分布式表:

ENGINE = Distributed(cluster_name, db_name, table_name[, sharding_key[, policy_name]])

參數:
cluster_name:集群名稱。
db_name:數據庫名稱,可使用常量表達式:currentDatabase()。
table_name: 各分片上的表名稱。
sharding_key: (可選)分片的key,可設置為rand()。
policy_name: (可選)策略名稱,用于存儲異步發送的臨時文件。

例如下面的/etc/metrika.xml的一部分內容:

<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>

這里定義了一個名為logs的集群名稱,它有兩個分片(shard)組成,每個分片包含兩個副本(replica)。

分片是包含數據的不同服務器(要讀取所有數據,必須訪問所有分片)。

副本是存儲復制數據的服務器(要讀取所有數據,訪問該分片上的任意一個副本上的數據即可)。

1.weight : 可選,寫入數據時分片的權重,建議忽略該配置。
2.internal_repliacation : 可選,同一時刻是否只將數據寫入其中一個副本。默認值:false(將數據寫入所有副本),建議設置為true。寫一個即可。避免重復寫。
3.副本配置:配置每個Server的信息,必須參數:host和port,可選參數:user、password、secure和compression。
(1)、host : 遠程服務器地址。支持IPv4和IPv6。也可指定域名,更改域名解析需 重啟服務。
(2)、port : 消息傳遞的TCP端口。配置文件的tcp_port指定的端口,通常設置為 9000。
(3)、user : 用于連接到服務的用戶名稱。默認值:true。在users.xml文件中配置 了訪問權限。
(4)、password:用于連接到遠程服務的密碼。默認值:空字符串。
(5)、secure : 使用ssl進行連接,通常還應該定義port=9440。
(6)、compression : 使用數據壓縮。默認值:true。

24.2.數據副本與復制表

只有MergeTree系列引擎支持數據副本,支持副本的引擎是在MergeTree引擎名稱的前面加上前綴 Replicated。
副本是表級別的而不是整個服務器級別的,因此服務器可以同時存儲復制表和非復制表。
副本不依賴于分片,每個分片都有自己獨立的副本。

副本表如:

ReplicatedMergeTree ReplicatedSummingMergeTree ReplicatedReplacingMergeTree ReplicatedAggregatingMergeTree ReplicatedCollapsingMergeTree ReplicatedVersionedCollapsingMergeTree ReplicatedGraphiteMergeTree

24.3.ZooKeeper整合

ClickHouse使用Apache ZooKeeper來存儲副本元信息, 在配置文件設置 zookeeper相關的參數。
ClickHouse在創建復制表的時候指定Zookeeper的目錄,指定的目錄會在建 表時自動創建。
如果ClickHouse的配置文件未配置ZooKeeper, 則無法創建復制表, 并且 任何存量的復制表都將是只讀的。
對本地復制表的查詢,不會使用ZooKeeper, 其查詢速度和非復制表一樣快。

本地復制表的數據插入,針對每個數據塊(一個塊最多有 max_insert_block_size = 1048576條記錄),會通過幾個事務將大約十個條目添加到Zookeeper。因此,與非復制表相比, 復制表的INSERT操作等 待時間稍長。

<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.創建復制表

復制表的引擎要以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);

引擎參數包含了變量,這些變量是在配置文件的”macros”部分配置的,例如:

<macros><layers>05</layers><shard>02</shard><replica>clickhouse1</replica> </macros>

Replicated*MergeTree引擎參數:
?zoo_path : ZooKeeper中表的路徑。
?replica_name : ZooKeeper中的副本名稱。

1.第一個參數ZooKeeper路徑組成:
(1)、通用前綴:/clickhouse/tables/,建議復制表都使用類似這樣的前綴。
(2)、分片標識符:{layer}-{shard},在本示例中,分片標識符有兩部分組成,只要保證分片標識符能唯一標識一個分片即可。
(3)、ZooKeeper節點名稱:table_name。節點名稱最好與表名相同,節點名稱在定義后不會更改,即使執行表的重命名操作。

2.第二個參數是副本名稱,用于標識同一個分片的不同副本。副本名稱只需要在每個shard中唯一即可。
上面的示例中,復制引擎的參數使用了變量替換。ClickHouse也支持使用顯示的參數。在這種情況下,不能使用分布式的DDL查詢(ON CLUSTER)。建議使用變量替換的方式傳入參數,降低出錯概率。

在每個副本服務器上運行CREATE TABLE語句,如果該分片的表在其他節點已經創建且有數據,則該新副本自動同步其他副本的數據。

24.5.副本同步機制

復制是多主異步的。
INSERT語句(以及ALTER)可在任意可用的服務器上執行。數據首先插入到本地的服務器 (即運行查詢的服務器),然后數據被復制到其他服務器。

由于復制是異步的,所以最近插入的數據出現在其他副本上會有一定的延遲。

如果部分副本不可用,則在它們可用時寫入數據。

如果副本可用, 則等待的時間是通過網絡傳輸壓縮數據塊所耗費的時間。

默認情況下, INSERT操作只需等待一個副本寫入成功后返回。如果僅將數據成功寫入一個 副本,并且該副本的服務器不再存在, 則存儲的數據將丟失。要啟動來自多個副本的寫入確 認機制,使用insert_quorum選項。

24.6.數據原子寫入與去重

INSERT查詢按照數據塊插入數據,每個數據塊最多max_insert_block_size(默認 max_insert_block_size = 1048576)條記錄。換言之, 如果INSERT插入少于1048576條記 錄,則插入操作是原子的。單個數據塊的寫入是原子的。

數據塊是去重的。 對于同一數據塊的多次寫入(相同大小的的數據塊,包含相同的行以及相 同的順序),該塊僅寫入一次。在出現網口故障等異常情況下, 客戶端應用程序不知道數據 是否已將數據成功寫入數據庫,因此可以簡單地重復執行INSERT查詢。相同的數據發送到哪 個副本進行插入并不重要,INSERT是冪等的。數據去重可通過參數 insert_deduplicate控 制,默認為0(開啟去重)。

在復制過程中, 只有插入的源數據通過網絡傳輸。進一步的數據轉換(合并)會在所有副本 上以相同的方式進行處理。 這樣可以最大限度減少網絡帶寬占用,這意味著當副本位于不同 的數據中心時,復制的效果也很好。

ClickHouse內部監控副本的數據同步,并能夠在發生故障后恢復。故障轉義是自動的(對于數據的微小差異)或半自動的(當數據的差異太大時,這可能表示配置錯誤)。

ClickHouse內部監控副本上的數據同步,并能夠在發生故障后恢復。故障轉移是自動的(對于數據的微小差異)或半自動的(當數據差異太大時,這可能表示配置錯誤)。

24.7.負載平衡策略

執行分布式查詢時,首先計算分片的每個副本的錯誤數,然后將查詢發送至最少錯誤的副本。如果沒有錯誤或者錯誤數相同,則按如下的策略查詢數據:
1.random(默認) : 將查詢發送至任意一個副本。
2.nearest_hostname : 將查詢發送至主機名最相似的副本。
3.in_order : 將查詢按配置文件中的配置順序發送至副本。
4.first_or_random : 選擇第一個副本,如果第一個副本不可用,隨機選擇一個可用的副本。

設置策略的方式:

set load_balancing = 'first_or_random';

24.8.案例

1.在所有節點執行如下語句:
創建本地復制表:

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);

執行效果圖:
在clickhouse1節點執行的效果圖如下:

clickhouse1 :) 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.10390000 │ │ 32 │ │ 192.168.106.10590000 │ │ 22 │ └─────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘ ┌─host────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐ │ 192.168.106.10690000 │ │ 11 │ └─────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘ ┌─host────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐ │ 192.168.106.10490000 │ │ 00 │ └─────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘4 rows in set. Elapsed: 0.419 sec. clickhouse1 :)

在clickhouse2-4上執行后的效果如下(提示已經存在了):

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.103900057 │ Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build))32 │ └─────────────────┴──────┴────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────┴──────────────────┘ ┌─host────────────┬─port─┬─status─┬─error─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─num_hosts_remaining─┬─num_hosts_active─┐ │ 192.168.106.104900057 │ Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build))20 │ │ 192.168.106.105900057 │ Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build))10 │ │ 192.168.106.106900057 │ Code: 57, e.displayText() = DB::Exception: Table default.table_local already exists. (version 20.9.3.45 (official build))00 │ └─────────────────┴──────┴────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────┴──────────────────┘ ← 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 :)

通過上面的案例可以知道,只要在一個節點上創建了副本表之后,在其它節點上也已經存在了。

創建分布式表:

CREATE TABLE table_distributed as table_local ENGINE = Distributed(mycluster, default, table_local, rand());

(1)、驗證副本的復制
在clickhouse1上,對本地表操作。

clickhouse1 :) insert into table_local values('2020-03-11 12:12:33',22,37);INSERT INTO table_local VALUESOk.1 rows in set. Elapsed: 0.017 sec. clickhouse1 :) select * from table_local;SELECT * FROM table_local┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:332237 │ └─────────────────────┴───────────┴────────┘1 rows in set. Elapsed: 0.002 sec. clickhouse1 :)

在clickhouse2上(clickhouse1的分片副本節點)上,驗證數據是否同步:

clickhouse2 :) select * from table_local;SELECT * FROM table_local┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:332237 │ └─────────────────────┴───────────┴────────┘1 rows in set. Elapsed: 0.019 sec. clickhouse2 :)

在clickhouse3-4上執行(即shard2上)。發現查詢不到結果,效果如下:

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)、驗證集群的功能
在任意節點查看分布式表的數據(都將出現下面的效果)。

clickhouse1 :) select * from table_distributed;SELECT * FROM table_distributed┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:332237 │ └─────────────────────┴───────────┴────────┘1 rows in set. Elapsed: 0.009 sec. clickhouse1 :)

在任意一個節點往分布式表里面插入5條數據:

insert into table_distributed values('2020-03-11 12:12:31', 21, 1); clickhouse4上執行 insert into table_distributed values('2020-03-12 12:12:32', 22, 2); clickhouse4上執行 insert into table_distributed values('2020-03-13 12:12:33', 23, 3); clickhouse3上執行 insert into table_distributed values('2020-03-14 12:12:34', 24, 4); clickhouse3上執行 insert into table_distributed values('2020-03-15 12:12:35', 25, 5); clickhouse2上執行

然后在任意一臺機器上執行:

select * from table_distributed;

都可以看到:

clickhouse1 :) select * from table_distributed;SELECT * FROM table_distributed┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:332237 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-12 12:12:32222 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-14 12:12:34244 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-15 12:12:35255 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:31211 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-13 12:12:33233 │ └─────────────────────┴───────────┴────────┘6 rows in set. Elapsed: 0.009 sec. clickhouse1 :)

然后,分別在兩個分片的主機上查詢本地表:
在clickhouse1-2上(shard1)發現的效果是:

clickhouse1 :) select * from table_local;SELECT * FROM table_local┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:332237 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-12 12:12:32222 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-14 12:12:34244 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-15 12:12:35255 │ └─────────────────────┴───────────┴────────┘ ↘ Progress: 4.00 rows, 48.00 B (1.76 thousand rows/s., 21.09 KB/s.) 4 rows in set. Elapsed: 0.004 sec. clickhouse1 :)

在clickhouse3-4上(shard2)發現的效果是:

clickhouse3 :) select * from table_local;SELECT * FROM table_local┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-11 12:12:31211 │ └─────────────────────┴───────────┴────────┘ ┌───────────EventDate─┬─CounterID─┬─UserID─┐ │ 2020-03-13 12:12:33233 │ └─────────────────────┴───────────┴────────┘2 rows in set. Elapsed: 0.002 sec. clickhouse3 :)

可以看到,使用分布式表插入數據,數據分散到不同分片(shard)的本地表。

總結

以上是生活随笔為你收集整理的18_clickhouse副本同步与高可用功能验证,分布式表与集群配置,数据副本与复制表,ZooKeeper整合,创建复制表,副本同步机制,数据原子写入与去重,负载平衡策略,案例(学习笔记)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。