1怔蚌、概述
- 下圖中N1和N2內(nèi)容不同桦踊,則N1 N2互為分片籍胯。如果內(nèi)容相同杖狼,則互為副本蝶涩。
分片與副本
2绿聘、數(shù)據(jù)副本
- 只有使用了ReplicatedMergeTree復制表系列引擎熄攘,才能應用副本能力挪圾。
- ReplicatedMergeTree增加了Zookeeper部分哲思,會進一步在ZooKeeper內(nèi)創(chuàng)建一系列的監(jiān)聽節(jié)點,并以此實現(xiàn)多個實例之間的通信也殖。
- ZooKeeper不會涉及表數(shù)據(jù)傳輸。
ReplicatedMergeTree
2.1 副本的特定
- 副本是定義在表級別的
- 多主架構
- Block數(shù)據(jù)塊是數(shù)據(jù)寫入的基本定遠己儒,并且具有寫入的原子性和唯一性捆毫。會計算Hash信息并記錄绩卤,通過Hash摘要對比是否唯一。
2.2 副本定義形式
ENGINE = ReplicatedMergeTree('zk_path', 'replica_name')
- 通常的zk_path命名
/clickhouse/tables/{shard}/table_name
- zk_path用于指定在ZK中創(chuàng)建的數(shù)據(jù)表的路徑
- 對于zk_path濒憋,同一張數(shù)據(jù)表的同一個分片的不同副本應該定義相同的路徑何暇。
- 對于replica_name,同一張數(shù)據(jù)表的同一個分片的不同副本應該定義不同名稱凛驮。
命名的例子
3裆站、ReplicatedMergeTree
3.1 數(shù)據(jù)結構
- 大量運用ZooKeeper能力,實現(xiàn)副本之間協(xié)同黔夭。
ZooKeeper內(nèi)的節(jié)點結構
- 元數(shù)據(jù)
/metadata
/columns
/replicas - 判斷標識
/leader_election
/blocks hash摘要
/block_numbers
/quorum 至少有quorum數(shù)量副本寫入成功后才算寫入成功 - 操作日志
/log
/mutations ALTER DELTE ALTER UPDATE等操作的記錄
/replicas/{replica_name}/*
Entry日志多項數(shù)據(jù)結構
- /log /mutations 是分發(fā)操作指令的信息通道宏胯,發(fā)送指令的方式是為這些父節(jié)點添加子節(jié)點。
- 添加的子節(jié)點在Clickhouse中被統(tǒng)一抽象為Entry對象本姥,具體實體由LogEntry和MutationEntry對象承載肩袍。
3.2 副本協(xié)同的核心流程
INSERT
INSERT流程
- 由執(zhí)行了INSERT操作的副本向/log節(jié)點推送操作日志婚惫。
- 副本會一直監(jiān)聽/log節(jié)點變化辰妙,拉取LogEntry鹰祸,將其轉為任務對象放至隊列密浑。
- 基于/queue隊列開始執(zhí)行任務蛙婴,會選擇一個遠端副本作為數(shù)據(jù)的下載來源。選取擁有最大log_pointer的尔破,并且/queue子節(jié)點數(shù)量最少的浇衬。然后建立起連接開始下載。
MERGE
- 無論MERGE操作從哪個副本發(fā)起,其合并計劃都會交由主副本來制定蚁阳。
MERGE過程
MUTATION
- 也是由主節(jié)點來制定計劃
ALTER
- 修改ZK內(nèi)的共享元數(shù)據(jù)節(jié)點。
/metadata /columns
ALTER
4、數(shù)據(jù)分片
- ClickHouse中的每個服務節(jié)點都稱為一個shard
- ClickHouse數(shù)據(jù)分片需要結合Distributed表引擎一同使用铝条,使得查詢贤壁、寫入能夠進行路由莹妒。
- Distributed表引擎本身不存儲任何數(shù)據(jù),知識作為分布式表的一層透明代理迷扇。
4.1 基于集群實現(xiàn)分布式DDL
CREATE/DROP/RENAME/ALTER TABLE ON CLUSTER cluster_name
數(shù)據(jù)結構
- 默認分布式DDL在ZK內(nèi)使用的根路徑為
/clickhouse/task_queue/ddl
- /query-[seq]/active /query-[seq]/finished
- DDLLogEntry日志對象數(shù)據(jù)中包含了 query厨内、hosts、initiator
分布式DDL執(zhí)行流程
- 誰執(zhí)行誰負責推送
- 拉取日志并執(zhí)行
- 步驟1執(zhí)行后获印,客戶端會阻塞180秒,等待所有host執(zhí)行完畢街州。
分布式DDL執(zhí)行
5兼丰、Distributed原理解析
- 由兩部分組成,本地表和分布式表唆缴,分布式表以all后綴命名鳍征。
- 采用讀時檢查,如果它們表結構不兼容面徽,只有在查詢時才拋出錯誤艳丛。
5.1 定義形式
ENGINE = Distributed(cluster, database, table [,shaeding_key])
CREATE TABLE test_shard_2_all ON CLUSTER sharding_simple ()
ENGINE = Distributed(sharding_simple, defalult, test_shard_2_local, rand())
- cluster 集群名稱
- sharding_key 分片鍵,選填參數(shù)
讀取模式
- Distributed表不支持任何MUTATION類型操作
5.2 分片規(guī)則
- 集群配置的分片權重趟紊,權重越大氮双,寫入數(shù)據(jù)越多
- slot 數(shù)量等于所有分片的權重之和
- 選擇函數(shù),slot = shard_value % sum_weight
5.3 寫入流程
- 在第一個分片節(jié)點寫入本地分片數(shù)據(jù)
- 建立遠端連接霎匈,準備發(fā)送遠端數(shù)據(jù)分片
- 發(fā)送數(shù)據(jù)
- 遠端分片寫入本地
- 第一個分片確認完成寫入
寫入流程
副本寫入
- 可以用Distributed復制戴差,也可以依賴ReplicatedgeTree
副本寫入
5.4 查詢過程
多副本路由:randon\nearest_hostname(錯誤最少)\in_order(錯誤最少中的按定義逐個選擇)\first_or_random 四種方式
分布式查詢是在本地查之后union的結果
分布式查詢執(zhí)行計劃
使用Global優(yōu)化分布式子查詢
- 使用本地表的問題
SELECT uniq(id) FROM test_query_all WHERE repo = 100 AND id IN (SELECT id FROM test_query_local WHERE repo = 200)
- 掃的本地表里剛好沒有這個數(shù)據(jù),有希望在全局里找铛嘱。
問題1
- 使用分布式表又會有查詢放大的問題暖释,每次掃all都是全局廣播,就會變成指數(shù)增長
SELECT uniq(id) FROM test_query_all WEHRE repo = 100 AND id IN (SELECT id FROM test_query_all WHERE repo = 200)
問題2
- 所以有一個GLOBAL關鍵字墨吓,可以將中間過程緩存
GLOBAL JOIN