在實務中,資料庫節點可能因硬體故障、軟體升級或網路問題而離線。如何確保資料不遺失、查詢不中斷,並且能夠在線進行升級與維護,高可用性 (High Availability, HA) 架構成為核心需求。
ClickHouse 提供了 Replicated Tables 機制,透過 主從副本同步(Replication)與自動 Failover 機制,實現資料一致性與讀取負載平衡,讓叢集具備「零停機升級」的能力。
Replicated Tables 是 ClickHouse 內建的一種資料複製技術,依賴 ClickHouse Keeper / ZooKeeper 作為協調器,實現以下功能:
大多數的 MergeTree 家庭成員都支援,包含:
這些引擎會在建立表格時透過
Replicated*MergeTree
來定義,並指定 ZooKeeper/ClickHouse Keeper 路徑與 Replica 名稱來實現資料副本同步。
CREATE TABLE table_name
(
EventDate DateTime,
CounterID UInt32,
UserID UInt32,
ver UInt16
)
ENGINE = ReplicatedReplacingMergeTree(
'/clickhouse/tables/{layer}-{shard}/table_name',
'{replica}',
ver
)
PARTITION BY toYYYYMM(EventDate)
ORDER BY (CounterID, EventDate, intHash32(UserID))
SAMPLE BY intHash32(UserID);
上述功能:當同一筆資料出現多個版本時(以 Primary Key 為基準),ClickHouse 會以 ver 欄位數值較大的版本作為最終結果(去重邏輯發生於 Merge 階段)。
什麼?忘記了,罰你回去看:ClickHouse 系列:ReplacingMergeTree 與資料去重機制 🫵
參數 | 說明 |
---|---|
/clickhouse/tables/{layer}-{shard}/table_name |
這是 Zookeeper/ClickHouse Keeper 中的 Metadata 路徑,每個 Replica 會註冊到這個路徑下。 {layer} 與 {shard} 會從 macros.xml 讀取。 |
{replica} |
代表該節點的 Replica 名稱 (例如 replica1, replica2),同樣從 macros.xml 讀取。 |
<yandex>
<macros>
<shard>01</shard>
<replica>replica1</replica>
</macros>
</yandex>
每個 Replica 節點都必須設定對應的 {shard}
與 {replica}
,以便在 ZooKeeper/Keeper 上正確標註其節點身份。
CREATE TABLE:
DROP TABLE:
ATTACH / DETACH TABLE:
RENAME TABLE:
所以 DDL 操作需由開發者自己控制 ON CLUSTER 或手動同步到每個 Replica 節點執行。
在 ClickHouse 設定檔中 (config.xml),需定義 ZooKeeper / Keeper 協調器:
<zookeeper>
<node>
<host>zk1</host>
<port>2181</port>
</node>
<node>
<host>zk2</host>
<port>2181</port>
</node>
<node>
<host>zk3</host>
<port>2181</port>
</node>
</zookeeper>
或者如果使用 ClickHouse Keeper:
<keeper_server>
...
</keeper_server>
故障場景 | ClickHouse 行為 |
---|---|
Replica (非主節點) 故障 | 該節點不會參與查詢,查詢自動切換至其他 Replica,不影響查詢可用性。 |
Primary Replica 故障 | 其他 Replica 會透過 Keeper 選舉新的 Primary,確保寫入不中斷。 |
Keeper 故障 (單節點失效) | 若為 Keeper 叢集,會自動選擇 Leader,除非多數節點故障才會影響副本同步。 |
設計策略 | 說明 |
---|---|
使用奇數數量的 Keeper 節點 (3 或 5 節點) | 確保故障容忍度達到 n/2,可支撐單點或雙點故障仍維持叢集協調運作。 |
分散 Replica 於不同可用區 (AZ) | 提升容災能力,確保單一區域失效不會影響整體叢集可用性。 |
設定 insert_quorum=2 以強化寫入一致性 | 可設定 Quorum Write 機制,保證至少 N 個副本成功寫入才返回成功。 |
使用 Distributed Table + ReplicatedMergeTree | 確保資料分片與副本同步結合,實現橫向擴展與高可用性並存的架構設計。 |
特性 | ClickHouse Cloud | 自行部署 ClickHouse |
---|---|---|
Replicated Table 建立 | 不需手動設定 Zookeeper,雲端服務自動協調。 | 需自行架設 ClickHouse Keeper / ZooKeeper。 |
副本與分片擴容 | 雲端服務可動態擴容,擴容過程對使用者透明。 | 自行部署時需手動加入節點並同步資料。 |
升級與維運 | 由雲端服務自動完成節點升級與容錯。 | 需自行規劃升級排程與 Failover 流程。 |
更高控制權 (細部參數調校) | 雲端部分功能會被封裝起來,無法自訂複雜參數。 | 可完整控制 clusters.xml、macros、Keeper 設定細節。 |
讀取查詢 (SELECT) 時並不會透過 ZooKeeper 進行協調,因此查詢效能與非複製表無異。
Distributed + Replicated 表查詢時,可透過以下參數控制 Replica 行為:
參數名 | 功能 |
---|---|
max_replica_delay_for_distributed_queries | 設定允許查詢的 Replica 最多可以落後多久(以秒為單位)。 |
fallback_to_stale_replicas_for_distributed_queries | 當同步 Replica 不可用時,是否允許回退至資料落後的 Replica 查詢。 |
你可能會想說:Vic,每秒不要超過 1 次 INSERT也太弱了吧?
我一開始也是這樣認為,但 ClickHouse 的意思是:「小批次(小 Data Part)高頻率 INSERT」的情況。若每秒進行大量筆數極少(幾百、幾千行)的 INSERT,會導致每次 INSERT 都需要進行 ZooKeeper 協調、Data Part 的寫入與同步,這會嚴重增加系統負載(ZooKeeper 會被灌爆 Bruh)。
建議還是將資料聚合成「大批次寫入」(例如:1秒寫1次,每次數十萬筆),降低 Data Part 產生數量,避免 ZooKeeper 壓力。
預設情況下,INSERT 只會等其中一個 Replica 確認寫入成功後就返回成功訊號。
這意味著若該 Replica 發生永久性故障,該筆資料有遺失風險。
若需保障寫入至少多個副本成功才能回應,應啟用:
SET insert_quorum = 2;
這樣只有當至少 2 個 Replica 確認成功寫入才會回傳成功。
參數名稱 | 功能 |
---|---|
background_schedule_pool_size | 控制執行背景合併 (Merge)、壓縮 (Mutations) 等任務的執行緒數量。 |
background_fetches_pool_size | 控制 Replicated Table 資料擷取 (Fetch) 任務的執行緒數量,需重啟伺服器才會生效。 |
項目 | 建議 |
---|---|
INSERT 頻率 | 建議每秒不超過 1 次 INSERT 操作,並將大量資料批次寫入 (Batch Inserts)。 |
ZooKeeper 負載 | 若 INSERT 頻率極高,可考慮將不同 Shard 使用不同 ZooKeeper 叢集。 |
跨資料中心同步 | Replicated Tables 特別適合用於跨資料中心的高可用同步場景。 |
一致性要求高的寫入 | 啟用 insert_quorum 參數來保障寫入多副本一致性。 |
透過 ClickHouse Replicated Tables 機制,我們能夠實現資料一致性、查詢負載平衡與真正的零停機升級 (Zero Downtime Upgrade)。
對於處理高頻寫入、大規模查詢且又要求高可用性的數據平台,這是不可或缺的核心架構設計。