clickhouse distribute 引擎深度解讀


什么是分發(fā)引擎?

分發(fā)引擎在業(yè)務用來建立all表時使用。

all表的概念可以理解為一個視圖。

在all表上讀數(shù)據(jù)時CH數(shù)據(jù)流程如下:

1.分發(fā)SQL到對應多個shard上執(zhí)行SQL

2.執(zhí)行SQL后的數(shù)據(jù)的中間結(jié)果發(fā)送到主server上

3.數(shù)據(jù)再次匯總過濾。

如下圖所示:


what happened when reading from distributed table


what happened when reading from distributed table

在各shard執(zhí)行SQL是自動且并行化的,無需參數(shù)配置或手動干預。讀數(shù)時隨機選擇某個shard的replica進行讀書。如果表有索引優(yōu)先使用索引。

分布式引擎接受參數(shù)有:服務器配置文件中的集群名稱,遠程數(shù)據(jù)庫的名稱,遠程表的名稱以及(可選)分片鍵。例:


Distributed(logs, default, hits[, sharding_key])

以上面的建表引擎作為例子。

參數(shù)說明:

logs :?服務器配置文件中的群集名稱。rpm包裝好后的配置文件在/etc/clickhouse-server/config.xml

default: 庫名,也可以使用常量表達式來代替數(shù)據(jù)庫名稱,如currentDatabase()

hits:表名

sharding_key:路由算法

上面引擎的隱喻是:定位logs集群,從位于群集中每個服務器上的“default.hits”表中讀取數(shù)據(jù)。數(shù)據(jù)將在遠程服務器部分處理。例如,對于使用GROUP BY的查詢,將在遠程服務器上聚合數(shù)據(jù),聚合函數(shù)的中間狀態(tài)將發(fā)送到請求者服務器。數(shù)據(jù)將會進一步聚合。

配置信息詳解

cluster logs的配置文件

這個配置文件一般叫做metrika.xml,當然你也可以給這個文件自定義一個名字,但是別忘了在主config.xml中通過include_from標簽包含進去。否則,服務會報找不到cluster的錯誤。metrika.xml 文件中一般存集群配置、ZK配置、分片配置等。

這個配置文件告訴我們說:

我定義了一個名字為"logs"的集群,由兩個shard(分片)組成,每個shard包含兩個副本。其中shard的概念,是指包含不同數(shù)據(jù)部分的服務器(所有Shard上的數(shù)據(jù)加起來是整個數(shù)據(jù)集)。副本是復制服務器(可以訪問任何副本上的數(shù)據(jù),副本是主主復制)。

對每個服務器來說,有兩個強制參數(shù)(host,port),兩個可選參數(shù)(user,password)。

host:?遠程服務器的主機地址??梢灾付橛蛎Pv4或IPv6地址。如果指定域,服務器將在啟動時執(zhí)行DNS查找。如果DNS請求失敗,服務器將無法啟動。如果修改了DNS記錄,請重新啟動服務器以使新記錄生效。

port:服務器之間通信的TCP端口(配置文件中的tcp_port,默認是9000)

user:連接到遠程服務器的用戶名稱。默認情況下,用戶是“default”。此用戶必須具有連接到遠程服務器的訪問權(quán)限。在users.xml配置文件訪問權(quán)限的管理。

password:以明文登錄到遠程服務器的密碼。默認為空字符串。

當一個讀取的sql落到一個shard上時,分片將選擇一個可用副本。當然你也可以通過配置負載均衡算法(副本訪問的優(yōu)先級,參閱‘load_balancing’設置)。如果與服務器的連接沒有建立成功,則在短暫超時后繼續(xù)嘗試連接。如果連接失敗,下一個副本將被選中,以此類推。如果所有副本的連接嘗試失敗,會以相同的方式重復幾次嘗試。與此同時,遠程服務器仍然會接受連接,但大概率不能正常提供服務。

在寫配置文件的時候,你可以只寫一個分片,這時候就沒有分發(fā)的概念了,因為所有的數(shù)據(jù)都將落在這一個shard上。你也可以搞N個分片,每個分片搞N個副本。每個分片的副本數(shù)量可以不同。

你也可以在配置文件中配任意數(shù)量的cluster。

查看集群

查看我當前有幾個集群,運行命令:

show cluster command

分發(fā)引擎讓你使用起來就好像在用本地服務器(其實它已經(jīng)在分布式的工作了)。注意,群集是不可擴展的:必須將其配置寫入每個服務器的配置文件。

不支持查看其他分布式表的Distributed表(除非分布式表只有一個分片)。作為替代方法,使分布式表查看“最終”表。

分發(fā)引擎需要編寫集群配置文件。修改后的配置的可熱更新,不需要重新啟動服務器。如果需要每次都向未知的分片和副本發(fā)送查詢,無需創(chuàng)建分布式表,推薦使用“遠程”表格功能。請參閱“table functions”。

有兩種將數(shù)據(jù)寫入集群的方法:

1. 你想往哪些服務器寫哪些數(shù)據(jù),直接通過分片去寫入。

2.通過distributed表灌數(shù),引擎將通過sharding key (最后一個參數(shù),必須指定)算法分散數(shù)據(jù)落到不同的服務器上。如果只有一個分片的情況下,無需指定sharding key。

每個分片都可以在配置文件中定義一個權(quán)重。默認情況下,權(quán)重等于1。數(shù)據(jù)以與分片權(quán)重成正比的量分布在分片上。例如,如果有兩個分片,第一個的權(quán)重是9,第二個的權(quán)重是10,則第一個將存放9/19數(shù)據(jù)集,第二個將存放10/19。

每個分片都可以在配置文件中定義“internal_replication”參數(shù)。如果此參數(shù)設置為“true”,則寫入操作會選擇第一個健康的replica并向其寫入數(shù)據(jù)。然后各個replica之間通過zookeeper自動同步數(shù)據(jù),類似于replicated表的數(shù)據(jù)同步模式。如果它設置為'false'(默認),數(shù)據(jù)將被寫入所有副本。實質(zhì)上,這意味著Distributed表本身復制數(shù)據(jù)。這比使用復制表要糟糕,因為副本的一致性未被檢查,并且隨著時間的推移,它們的數(shù)據(jù)會存在部分不一致的情況。

分片表達式(sharding key)

分析分片的表達式(sharding key)用來決定將數(shù)據(jù)寫入到哪個分片。

最后一項sharding_key是可選的,可以是一個表達式,例如rand(),可以是一列 例如user_id,(integer類型),通過對余數(shù)值進行取余分片,(rand()函數(shù)返回值/shards總權(quán)重)【這有個好處就是特定的Userid會落到特定的分片上,從而簡化了用戶的in和join操作】。如果擔心分片數(shù)據(jù)不均勻,也可以加上hash函數(shù),如intHash64(user_id)

假設現(xiàn)在來了一條數(shù)據(jù),這條數(shù)據(jù)要寫到哪個分片呢?我們來看看這里的算法實現(xiàn)。

首先假設我們有3個分片,權(quán)重分別是9,10,11。

3個shard分割出如下3個權(quán)重空間[0,9);[9,19);[19,30]。其中,第一個shard擁有第一個權(quán)重空間,第二個shard擁有第二個權(quán)重空間,第3個shard擁有第三個權(quán)重空間。

權(quán)重空間分割的計算方式:[prev_weight,pre_weights+weight) ... 其中,prev_weights是最左分片權(quán)重的總和,weight表示當前shard權(quán)重,示例如上。

現(xiàn)在來了一條待寫入的row,我們看看寫入時發(fā)生了什么?

1.sharding key表達式先被解析,假定sharding key表達式是rand()函數(shù),函數(shù)返回值是43。

2.函數(shù)返回值/shards權(quán)重總和=43/(9+10+11) = 13

3.查找13屬于范圍[9,19),這個權(quán)重空間屬于第二個shard,于是,數(shù)據(jù)將落到第二個shard上。

對于sharding key的選擇來說,劃分的一個簡單的余數(shù)(rand算法)是分片的有限解決方案,并不總是合適的。它適用于大中型數(shù)據(jù)(數(shù)十臺服務器),但不適用于大量數(shù)據(jù)(數(shù)百臺服務器或更多)。在后一種情況下,使用主題區(qū)域所需的分片方案,不建議使用distribute表中的條目。

當使用復制表格時,可以復制數(shù)據(jù) - 查看“resharding”部分。但在許多情況下,最好不要這樣做。SELECT查詢被發(fā)送到所有的分片,并且無論數(shù)據(jù)如何分布在分片上(它們可以完全隨機地分配),都可以工作。當你添加一個新的分片時,可以給這個shard配一個較重的權(quán)重 - 數(shù)據(jù)會有一部分落到這個shard上,這導致整體cluster的數(shù)據(jù)分布稍微不均勻,但不會影響正常查詢。

分片方案

在以下場景,應該關(guān)注設計分片方案:

?- 使用查詢需要通過特定的鍵來連接數(shù)據(jù)(IN或JOIN)。如果數(shù)據(jù)被這個鍵分割,你可以使用本地IN或JOIN而不是GLOBAL IN或GLOBAL JOIN,這樣更有效率。?

- 使用大量的服務器(數(shù)百個或更多)以及大量的小型查詢(來自各個不同個體的客戶端 、 網(wǎng)站,廣告商或合作伙伴)。為了使小型查詢不影響整個集群,在單個分片上定位單個客戶端的數(shù)據(jù)是很有意義的?;蛘?,正如我們在Yandex.Metrica中所做的那樣,您可以設置雙層分片:將整個集群劃分為“層”,其中一個層可以由多個分片組成。單個客戶端的數(shù)據(jù)位于單個圖層上,但是可以根據(jù)需要將分片添加到圖層中,在他們內(nèi)部分發(fā)。為每個層創(chuàng)建分布式表,并為全局查詢創(chuàng)建一個共享的分布式表。(聽上去很高大上,這對提供大數(shù)據(jù)的基礎(chǔ)服務提供了一點兒新思路)

數(shù)據(jù)是異步寫入的。對于分配給表的INSERT ,數(shù)據(jù)塊只寫入本地文件系統(tǒng)。數(shù)據(jù)盡快發(fā)送到后臺的遠程服務器。你應該通過檢查表目錄/var/lib/clickhouse/data/database/table /中的文件列表(等待發(fā)送的數(shù)據(jù))來檢查數(shù)據(jù)是否成功發(fā)送。

如果服務器在INSERT到Distributed表之后宕機或重啟(例如,在設備出現(xiàn)故障后),插入的數(shù)據(jù)可能會丟失。如果在表目錄中檢測到損壞的數(shù)據(jù)部分,則將其轉(zhuǎn)移到“已損壞”的子目錄中,不再使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 目錄;(一) 拆分實施策略和示例演示(二) 全局主鍵生成策略(三) 關(guān)于使用框架還是自主開發(fā)以及sharding實...
    linking12閱讀 10,570評論 1 52
  • Sharding的基本思想其實就是采用分治的思想,要把一個數(shù)據(jù)庫切分成多個部分放到不同的數(shù)據(jù)庫(server)上,...
    jiangmo閱讀 9,650評論 0 7
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • 1、平臺無關(guān)性 Java屬于目標代碼級平臺無關(guān)語言類型,主要靠Java虛擬機JVM來實現(xiàn)。對高級語言的翻譯方式有解...
    Megatron9527閱讀 508評論 0 0
  • 那次公園長談之后,知道了李薇做小三兒也是迫不得已,我對她由最初的嫌棄、遠離漸漸又多出一些同情。 但對她的言談舉止和...
    c34d5a414b92閱讀 304評論 0 2

友情鏈接更多精彩內(nèi)容