Clickhouse架構及應用

內容大綱:

  1. 背景;
  2. Clickhouse介紹;
  3. Clickhouse架構及性能;
  4. Clickhouse在好未來的實踐;
  5. 建設與規劃;
  6. 參考文獻。

背景

在日誌中心發展早期,日誌檢索分析主要基於elasticsearch進行,隨着日誌中心接入的業務越來越多,數據量也逐漸增長,基於日誌進行分析和監控告警的需求變得越來越複雜,很難用elasticsearch來滿足,所以需要根據需求場景來選擇合適數據庫。我們需要的:

  • 數據量會很大,因此需要分佈式;
  • 支持實時寫入,支持快速計算,在較短時間內能完成計算;
  • 強大的sql能力,實時指標sql化;
  • 人力有限,運維需要簡單;
  • 高效的壓縮比存儲,服務器有限,可以用更少的服務器存儲更多的數據;

基於以上特點,我們選擇了Clickhouse,接下來會介紹Clickhouse的特點、系統架構以及使用情況。

Clickhouse介紹

1、Clickhouse特點

圖2-1 Clickhouse特點圖

可以看到,Clickhouse的特點恰是我們所需要的。接下來詳細的介紹一下核心特性:

1)完備的DBMS功能:

ClickHouse擁有完備的管理功能,所以它稱得上是一個DBMS ( Database Management System,數據庫管理系統 ),而不僅是一個數據庫。

作爲一個DBMS,它具備了一些基本功能,如:

  • DDL ( 數據定義語言 ):可以動態地創建、修改或刪除數據庫、表和視圖,而無須重啓服務;
  • DML ( 數據操作語言 ):可以動態查詢、插入、修改或刪除數據;
  • 權限控制:可以按照用戶粒度設置數據庫或者表的操作權限,保障數據的安全性;
  • 數據備份與恢復:提供了數據備份導出與導入恢復機制,滿足生產環境的要求;
  • 分佈式管理:提供集羣模式,能夠自動管理多個數據庫節點。

2) 列式存儲與數據壓縮

列式存儲和數據壓縮,對於一款高性能數據庫來說是必不可少的特性。想讓查詢變得更快,最簡單且有效的方法是減少數據掃描範圍和數據傳輸時的大小,而列式存儲和數據壓縮就可以幫助我們實現上述兩點。由於Clickhouse是真正意義上的列式存儲,每一列都在不同的文件下,所以該文件數據類型一致,可以更有效的壓縮。

3) 向量化執行引擎

向量化執行以列存爲前提,主要思想是每次從磁盤上讀取一批列,這些列以數組形式組織。每次next都通過for循環處理列數組。這麼做可以大幅減少next的調用次數。相應的CPU的利用率得到了提高,另外數據被組織在一起。

可以進一步利用CPU硬件的特性,如SIMD,將所有數據加載到CPU的緩存當中去,提高緩存命中率,提升效率。在列存儲與向量化執行引擎的雙重優化下,查詢執行的速度會有一個非常巨大的飛躍。

4) 關係模型與SQL查詢

ClickHouse是一個關係型數據庫。它幾乎可以支持近百分之九十的sql作爲查詢語句,比如group by,order by等。

5) 多樣化的表引擎

ClickHouse和mysql一樣,也將存儲部分進行了抽象,把存儲引擎作爲一層獨立的接口。所以說Clickhouse實現了很多種表引擎,比如mergetree,log,memory等類型的引擎,每一種表引擎都有着各自的特點,用戶可以根據實際業務場景的要求,選擇合適的表引擎使用。

6) 多線程與分佈式
ClickHouse幾乎具備現代化高性能數據庫的所有典型特徵,對於可以提升性能的手段可謂是一一用盡,對於多線程和分佈式這類被廣泛使用的技術,自然更是不在話下。

7) 多主架構

HDFS、Spark、HBase和Elasticsearch這類分佈式系統,都採用了Master-Slave主從架構,由一個管控節點作爲Leader統籌全局。而ClickHouse則由於它的集羣架構和其他數據庫不同,這種架構使得它是一個多主架構。

8) 在線查詢

ClickHouse採用了LSM樹結構,所以使得Clickhouse的插入量可以很大。同時,Clickhouse的內部優化,使得在複雜查詢的場景下,它也能夠做到極快響應,且無須對數據進行任何預處理加工。達到了實時數倉的效果

9) 數據分片與分佈式查詢

Clickhouse擁有分佈式能力,自然支持數據分片,數據分片是將數據進行橫向切分,這是一種在面對海量數據的場景下,解決存儲和查詢瓶頸的有效手段。ClickHouse並不像其他分佈式系統那樣,擁有高度自動化的分片功能。ClickHouse提供了本地表 ( Local Table ) 與分佈式表 ( Distributed Table ) 的概念。一張本地表等同於一份數據的分片。而分佈式表本身不存儲任何數據,它是本地表的訪問代理,其作用類似分庫中間件。藉助分佈式表,能夠代理訪問多個數據分片,從而實現分佈式查詢。

2、C****lickhouse常見應用場景

  • 電信行業用於存儲數據和統計數據使用;
  • 新浪微博用於用戶行爲數據記錄和分析工作;
  • 用於廣告網絡和RTB,電子商務的用戶行爲分析;
  • 日誌分析;
  • 檢測和遙感信息的挖掘;
  • 商業智能;
  • 網絡遊戲以及物聯網的數據處理和價值數據分析;
  • 最大的應用來自於Yandex的統計分析服務Yandex.Metri ca。

Clickhouse架構及性能

Clickhouse的集羣架構是和其他的數據集羣有一定的區別,他的集羣能力是表級別的,而我們熟知的大數據體系,比如hadoop系列的集羣都是服務級別的。例如,一個hdfs集羣,所有文件都會切片、備份;而Clickhouse集羣中,建表時也可以自己決定用不用,也就是說其實Clickhouse單節點就能存活。可能有其他的大數據經驗的人對這種設計會有點奇怪,後面會從單機架構到集羣架構,詳細的去介紹。

=======================================================================================================================================================================================================

1、Clickhouse單機架構設計

官方介紹Clickhouse架構的資料比較匱乏,依據已有的經驗結合外部資料,根據自己的理解還原Clickhouse的架構如下:


圖3-1 clickhouse單機架構圖

1)Parser與Interpreter

Parser和Interpreter是非常重要的兩組接口:Parser分析器是將sql語句已遞歸的方式形成AST語法樹的形式,並且不同類型的sql都會調用不同的parse實現類。而Interpreter解釋器則負責解釋AST,並進一步創建查詢的執行管道。Interpreter解釋器的作用就像Service服務層一樣,起到串聯整個查詢過程的作用,它會根據解釋器的類型,聚合它所需要的資源。首先它會解析AST對象;然後執行"業務邏輯" ( 例如分支判斷、設置參數、調用接口等 );最終返回IBlock對象,以線程的形式建立起一個查詢執行管道。

2)表引擎

表引擎是ClickHouse的一個顯著特性,上文也有提到,clickhouse有很多種表引擎。不同的表引擎由不同的子類實現。表引擎是使用IStorage接口的,該接口定義了DDL ( 如ALTER、RENAME、OPTIMIZE和DROP等 ) 、read和write方法,它們分別負責數據的定義、查詢與寫入。

3)DataType

數據的序列化和反序列化工作由DataType負責。根據不同的數據類型,IDataType接口會有不同的實現類。DataType雖然會對數據進行正反序列化,但是它不會直接和內存或者磁盤做交互,而是轉交給Column和Filed處理。

4)Column與Field

Column和Field是ClickHouse數據最基礎的映射單元。作爲一款百分之百的列式存儲數據庫,ClickHouse按列存儲數據,內存中的一列數據由一個Column對象表示。Column對象分爲接口和實現兩個部分,在IColumn接口對象中,定義了對數據進行各種關係運算的方法,例如插入數據的insertRangeFrom和insertFrom方法、用於分頁的cut,以及用於過濾的filter方法等。而這些方法的具體實現對象則根據數據類型的不同,由相應的對象實現,例如ColumnString、ColumnArray和ColumnTuple等。在大多數場合,ClickHouse都會以整列的方式操作數據,但凡事也有例外。如果需要操作單個具體的數值 ( 也就是單列中的一行數據 ),則需要使用Field對象,Field對象代表一個單值。與Column對象的泛化設計思路不同,Field對象使用了聚合的設計模式。在Field對象內部聚合了Null、UInt64、String和Array等13種數據類型及相應的處理邏輯。

5)Block

ClickHouse內部的數據操作是面向Block對象進行的,並且採用了流的形式。雖然Column和Filed組成了數據的基本映射單元,但對應到實際操作,它們還缺少了一些必要的信息,比如數據的類型及列的名稱。於是ClickHouse設計了Block對象,Block對象可以看作數據表的子集。Block對象的本質是由數據對象、數據類型和列名稱組成的三元組,即Column、DataType及列名稱字符串。Column提供了數據的讀取能力,而DataType知道如何正反序列化,所以Block在這些對象的基礎之上實現了進一步的抽象和封裝,從而簡化了整個使用的過程,僅通過Block對象就能完成一系列的數據操作。在具體的實現過程中,Block並沒有直接聚合Column和DataType對象,而是通過ColumnWith TypeAndName對象進行間接引用。

2、Clickhouse集羣架構設計

Clickhouse是集羣是通過配置clickhouse_remote_servers來管理集羣的。在配置中,可以配置集羣名字,集羣所需要節點的信息,通過這些節點可以配置分片和副本機制。

簡單的配置爲例:

<yandex>
 <clickhouse_remote_servers>
 <cluster1>
 <shard>
 <internal_replication>true</internal_replication>
 <replica>
 <host>clickhouse-node1</host>
 <port>9000</port>
 </replica>
 <replica>
 <host>clickhouse-node2</host>
 <port>9001</port>
 </replica>
 </shard>
 <shard>
 <internal_replication>true</internal_replication>
 <replica>
 <host>clickhouse-node3</host>
 <port>9000</port>
 </replica>
 <replica>
 <host>clickhouse-node4</host>
 <port>9001</port>
 </replica>
 </shard>
 ...
 </cluster1>
 ...
 </clickhouse_remote_servers>
 ...
</yandex>

以上集羣配置完之後,想要用到Clickhouse的集羣能力,還需要使用Replicated_MergeTree+Distributed引擎,該引擎是"本地表 + 分佈式表"的方式,因此可以實現多分片多副本;下面具體介紹下Replicated_MergeTree引擎和Distributed引擎。

1)Replicated*MergeTree引擎

首先需要介紹下MergeTree引擎,這也是Clickhouse存儲數據的最核心引擎,之前所說的特點主要就是針對該引擎所描述的。MergeTree引擎則是在MergeTree基礎上中擴展了一些功能引擎,包括支持ReplacingMergeTree,SummingMergeTree等等MergeTree家族引擎,詳細瞭解可看官網mergetree引擎介紹,不帶replication的MergeTree引擎都可以看成單機引擎,也就是說它們是在單節點上存在的。

而使用Replicated_MergeTree就是將MergeTree引擎的數據通過Zookeeper調節,達到副本的效果。比如上述配置中,我們首先可以在cluster1中的每個節點上創建Replicated_MergeTr ee表,通過配置文件,可以看到Clickhouse-node1和Clickho use-node2是在同一個shard裏的,每個shard標籤裏的replica就代表複製節點。這時我們創建表時將兩個副本指定在同一個zo okeeper目錄下,那麼寫入到node1的數據會複製到node2,寫入node2的數據會同步到node1,達到預計的複製效果。

到這裏,每個節點上的本地表已經完成,但是多個分片的數據如何進行彙總,則需要下面的Distributed引擎。

**2)**Distributed引擎

使用Distributed引擎的表本身不存儲任何數據,但允許在多個服務器上進行分佈式查詢處理,讀取是自動並行的。在讀取期間,會使用遠程服務器上的表索引(也就是我們上述使用的Replicate d*MergeTree引擎)。

在讀寫數據時,如果使用Distributed表,可以按照配置文件配置的分片方案,從不同分片(shard)中讀寫數據,做到數據分片的效果。比如我們讀取數據時,是通過Distributed引擎表讀取,這個時候它會讀取集羣中的每個分片的數據做彙總計算。注意,這一塊會有深度分頁的情況,有些sql可以先分散在每個節點上執行完再在查詢節點做結果聚合,而有些則無法做結果聚合,必須將所有數據同步到查詢節點,由查詢節點統一彙總,這種情況就需要根據具體的數據情況進行優化。


圖3-2 本地表加分佈式表的查詢流程圖

圖3-2是一個2分片2副本的架構,使用的是Replicated*Merge Tree + Distributed引擎模式。紅色的數字代表節點的話,也就是節點1和2互爲副本,3和4互爲副本。

圖中events爲Distributed引擎表,也叫分佈式表;events_loc al爲Replicated*MergeTree引擎表,也叫本地表。該圖中,分佈式表只在節點3中創建,線上環境一般會在每個節點上都創建一個分佈式表(不會消耗資源,因爲分佈式表不會存儲數據)。

執行查詢時,會訪問一個節點的分佈式表,該圖中訪問的是節點3中分佈式表。然後分佈式表會分別的讀取2個分片的數據,在這裏,它讀取了節點3和節點2的本地表數據,這兩個節點加在一塊就是完整的數據。彙總查詢後將結果(Result Set)返回。

3、Clickhouse性能

**1)插入:**單機100-150M/s的插入速度;

**2)查詢:**單字段groupby沒有索引,1億數據查詢需要2.324s。有索引下,查詢時間爲0.101秒。可以看到Clickhouse的查詢速度是及其快的,市面上常見的數據庫基本都達不到這種性能;

**3)其他:**併發,官網默認配置爲100。由於是大數據分析數據庫主要適用於olap場景,對併發支持略差多個大數據查詢可能會直接將cpu等資源佔滿,故併發實際達不到100。

Clickhouse在好未來的實踐


圖4-1 clickhouse線上架構圖

1、業務場景

目前在好未來除了我們部門,在其他部門也已經有了多個業務方。

1) 本部門

使用平臺:日誌中心,貓頭鷹,土撥鼠,grafana等。

使用方式:我們將需要的數據通過flink,spark,gohangout等工具消費kakfa,寫入clickhouse,然後通過clickhouse做聚合查詢,將數據展示出來。

比如,土撥鼠主要是通過網關數據做的聚合,可以看到各個域名,url或者服務器的調用次數,請求耗時等情況。再比如直播數據則是消費直播上報日誌,用grafana將數據展示出來。

2) 其他部門

除了在本部門,還有其他業務方,數據研發部,數據中臺等也都在使用,數據研發部主要會將hive中的熱點數據通過spark/dataX同步至Clickhouse。然後將數據通過天樞天璇等平臺展示給分析師使用,提高了查詢速度。


圖4-2:clickhouse使用圖

2、存儲現狀


圖4-3 單節點數據存儲情況

以上數據第一列爲庫名,第二列爲行數,第三列爲壓縮前大小,第四列爲壓縮後大小。

可以看到單個節點已有多個達到TB級別和百億級別行數的數據庫。目前數據節點是6個,也就是說在集羣中,數據量需要再乘以6,代表有個別庫庫行數已達到千億行,容量達到百T級別。

建設與規劃

1、監控

Clickhouse官方目前沒有提供直接的監控界面,但是所需要的監控數據在system庫中都會記錄下來,網上已有人通過grafana展示出來,目前的監控圖如圖5-1所示。

圖5-1 clickhouse監控圖

除此之外,還寫了腳本,定期的對每個節點的探活及故障重啓。同時也使用神樹平臺查看各個節點的硬件信息及告警。

2、遇到的問題

Clickhouse作爲olap數據庫,在使用過程中或多或少會出現一些問題,例如版本bug,使用不規範,混部出現的問題等,現在主要介紹幾個需要持續優化或者業務配合的問題。其他遇到的一些問題也會在wiki上持續更新:

1) 大量查詢導致服務器負載高情況,影響業務查詢

**分析:**多個複雜查詢,並且命中數據量極大的情況下。每個查詢都會佔用大量的cpu和內存。會導致服務器負載被打滿的情況。尤其是內存被打滿,會造成節點掛掉的現象。
解決:

  • 用戶限制,避免內存被打滿,可以配置max_memory_us age_ for_all_queries,使其低於服務器實際內存。並且還可以限制用戶的併發,每次查詢的數據量等;
  • 某些業務下無法限制查詢數據量,可以添加緩存機制,避免大量大數據查詢。

2) ddl語句卡死

分析:Clickhouse主要支持的是追加及查詢,但是使用mergetr ee引擎的表,是可以做update和delete的。更新和刪除操作是用alter table語句的,也就是說其實這是需要ddl的權限的。每一次這種操作,數據庫都會發生加鎖,更新表等操作,並且數據量大的情況下,做更新操作,整個數據都會根據索引情況重新排序,這是一個漫長的過程。Clickhouse的ddl語句底層應該是個隊列,一個沒執行完,也會導致其他ddl卡住。

**解決:**儘量減少ddl語句的執行頻率以及增加執行間隔,或者儘量不要執行。

3) zookeeper失聯

**分析:**Clickhouse集羣方案很依賴zk,副本同步機制都是依賴zk的,導致每次插入數據都會和zk做交互,並且在zk中做寫操作,插入併發高的情況下,可能會導致zk暫時失聯。

**解決:**之前zookeeper是和Clickhouse混部,後期做了拆分,情況有一部分好轉。但是目前依然會偶爾出現問題,後續會繼續對這塊優化,zookeeper的服務器性能也會去儘量完善,申請高配服務器,提高zookeeper的性能,使得不會因爲zookeeper性能而影響到Clickhouse。

3、未來規劃

想要打造一個高性能高穩定的大數據場景數據庫,需要的是持續不斷地學習以及和業務方的配合。

  • 深入瞭解業務,根據業務場景建表;
  • 持續學習clickhouse,根據clickhouse特性優化sql;
  • 同時也需要業務方配合,如果大查詢頻率較高,可以考慮使用緩存等機制,或者特定場景可以使用近似計算。同時特殊場景特殊對待,實現合適的sql;
  • 數據持續增長,查詢壓力也是越來越大,進行集羣之間的隔離,使其重要業務之間不會互相影響;
  • 持續完善監控和告警機制;
  • clickhouse還有很多強大的功能,未來也會去嘗試使用。

參考文獻

[1]https://clickhouse.tech/docs
[2]https://blog.csdn.net/tzs_104...
[3]https://www.jianshu.com/p/ab8..

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章