大數據技術與架構 大數據技術與架構git
2020年下半年在OLAP領域有一匹黑馬以席捲之勢進入大數據開發者的領域,它就是ClickHouse。在2019年小編也曾介紹過ClickHouse,你們能夠參考這裏進行入門:github
來自俄羅斯的兇猛彪悍的分析數據庫-ClickHouse
基於ClickHouse的用戶行爲分析實踐
Prometheus+Clickhouse實現業務告警算法
那麼咱們有必要先從全局瞭解一下ClickHouse究竟是個什麼樣的數據庫?
ClickHouse是一個開源的,面向列的分析數據庫,由Yandex爲OLAP和大數據用例建立。ClickHouse對實時查詢處理的支持使其適用於須要亞秒級分析結果的應用程序。ClickHouse的查詢語言是SQL的一種方言,它支持強大的聲明性查詢功能,同時爲最終用戶提供熟悉度和較小的學習曲線。
ClickHouse全稱是Click Stream,Data Warehouse,簡稱ClickHouse就是基於頁面的點擊事件流,面向數據倉庫進行OLAP分析。ClickHouse是一款開源的數據分析數據庫,由戰鬥民族俄羅斯Yandex公司研發的,Yandex是作搜索引擎的,就相似與Google,百度等。
咱們都知道搜索引擎的營收主要來源與流量和廣告業務,因此搜索引擎公司會着重分析用戶網路流量,像Google有Anlytics,百度有百度統計,那麼Yandex就對應於Yandex.Metrica。ClickHouse就式在Yandex.Metrica下產生的技術。
面向列的數據庫將記錄存儲在按列而不是行分組的塊中。經過不加載查詢中不存在的列的數據,面向列的數據庫在完成查詢時花費的時間更少。所以,對於某些工做負載(如OLAP),這些數據庫能夠比傳統的基於行的系統更快地計算和返回結果。sql
根據官網的介紹(https://clickhouse.tech/benchmark/dbms/),ClickHouse在相同的服務器配置與數據量下,平均響應速度:數據庫
ClickHouse主要特色:設計模式
ClickHouse 採用了典型的分組式的分佈式架構,集羣架構以下圖所示:
這其中的角色包括:安全
ClickHouse的特性有不少,一款被承認的OLAP引擎可以獲得你們的頻繁使用必定是有獨特的特性,小編列舉了幾個ClickHouse異於常人的特性:
列式存儲&數據壓縮
按列存儲與按行存儲相比,前者能夠有效減小查詢時所需掃描的數據量,這一點能夠用一個示例簡單說明。假設一張數據表A擁有50個字段A1~A50,以及100行數據。如今須要查詢前5個字段並進行數據分析,那麼經過列存儲,咱們僅需讀取必要的列數據,相比於普通行存,可減小 10 倍左右的讀取、解壓、處理等開銷,對性能會有質的影響。
若是數據按行存儲,數據庫首先會逐行掃描,並獲取每行數據的全部50個字段,再從每一行數據中返回A1~A5這5個字段。不難發現,儘管只須要前面的5個字段,但因爲數據是按行進行組織的,實際上仍是掃描了全部的字段。若是數據按列存儲,就不會發生這樣的問題。因爲數據按列組織,數據庫能夠直接獲取A1~A5這5列的數據,從而避免了多餘的數據掃描。
按列存儲相比按行存儲的另外一個優點是對數據壓縮的友好性。ClickHouse的數據按列進行組織,屬於同一列的數據會被保存在一塊兒,列與列之間也會由不一樣的文件分別保存 ( 這裏主要指MergeTree表引擎 )。數據默認使用LZ4算法壓縮,在Yandex.Metrica的生產環境中,數據整體的壓縮比能夠達到8:1 ( 未壓縮前17PB,壓縮後2PB )。列式存儲除了下降IO和存儲的壓力以外,還爲向量化執行作好了鋪墊。性能優化
坊間有句玩笑,即"能用錢解決的問題,千萬別花時間"。而業界也有種調侃一模一樣,即"能升級硬件解決的問題,千萬別優化程序"。有時候,你千辛萬苦優化程序邏輯帶來的性能提高,還不如直接升級硬件來得簡單直接。這雖然只是一句玩笑不能當真,但硬件層面的優化確實是最直接、最高效的提高途徑之一。向量化執行就是這種方式的典型表明,這項寄存器硬件層面的特性,爲上層應用程序的性能帶來了指數級的提高。
向量化執行,能夠簡單地看做一項消除程序中循環的優化。這裏用一個形象的例子比喻。小胡經營了一家果汁店,雖然店裏的鮮榨蘋果汁深受你們喜好,但客戶老是抱怨製做果汁的速度太慢。小胡的店裏只有一臺榨汁機,每次他都會從籃子裏拿出一個蘋果,放到榨汁機內等待出汁。若是有8個客戶,每一個客戶都點了一杯蘋果汁,那麼小鬍鬚要重複循環8次上述的榨汁流程,才能榨出8杯蘋果汁。若是製做一杯果汁須要5分鐘,那麼所有制做完畢則須要40分鐘。爲了提高果汁的製做速度,小胡想出了一個辦法。他將榨汁機的數量從1臺增長到了8臺,這麼一來,他就能夠從籃子裏一次性拿出8個蘋果,分別放入8臺榨汁機同時榨汁。此時,小胡只須要5分鐘就可以製做出8杯蘋果汁。爲了製做n杯果汁,非向量化執行的方式是用1臺榨汁機重複循環制做n次,而向量化執行的方式是用n臺榨汁機只執行1次。
爲了實現向量化執行,須要利用CPU的SIMD指令。SIMD的全稱是Single Instruction Multiple Data,即用單條指令操做多條數據。現代計算機系統概念中,它是經過數據並行以提升性能的一種實現方式 ( 其餘的還有指令級並行和線程級並行 ),它的原理是在CPU寄存器層面實現數據的並行操做。
在計算機系統的體系結構中,存儲系統是一種層次結構。典型服務器計算機的存儲層次結構如圖1所示。一個實用的經驗告訴咱們,存儲媒介距離CPU越近,則訪問數據的速度越快。
從上圖中能夠看到,從左向右,距離CPU越遠,則數據的訪問速度越慢。從寄存器中訪問數據的速度,是從內存訪問數據速度的300倍,是從磁盤中訪問數據速度的3000萬倍。因此利用CPU向量化執行的特性,對於程序的性能提高意義非凡。
ClickHouse目前利用SSE4.2指令集實現向量化執行。服務器
相比HBase和Redis這類NoSQL數據庫,ClickHouse使用關係模型描述數據並提供了傳統數據庫的概念 ( 數據庫、表、視圖和函數等 )。與此同時,ClickHouse徹底使用SQL做爲查詢語言 ( 支持GROUP BY、ORDER BY、JOIN、IN等大部分標準SQL ),這使得它平易近人,容易理解和學習。由於關係型數據庫和SQL語言,能夠說是軟件領域發展至今應用最爲普遍的技術之一,擁有極高的"羣衆基礎"。也正由於ClickHouse提供了標準協議的SQL查詢接口,使得現有的第三方分析可視化系統能夠輕鬆與它集成對接。在SQL解析方面,ClickHouse是大小寫敏感的,這意味着SELECT a 和 SELECT A所表明的語義是不一樣的。
關係模型相比文檔和鍵值對等其餘模型,擁有更好的描述能力,也可以更加清晰地表述實體間的關係。更重要的是,在OLAP領域,已有的大量數據建模工做都是基於關係模型展開的 ( 星型模型、雪花模型乃至寬表模型 )。ClickHouse使用了關係模型,因此將構建在傳統關係型數據庫或數據倉庫之上的系統遷移到ClickHouse的成本會變得更低,能夠直接沿用以前的經驗成果。網絡
也許由於Yandex.Metrica的最初架構是基於MySQL實現的,因此在ClickHouse的設計中,可以察覺到一些MySQL的影子,表引擎的設計就是其中之一。與MySQL相似,ClickHouse也將存儲部分進行了抽象,把存儲引擎做爲一層獨立的接口。截至本書完稿時,ClickHouse共擁有合併樹、內存、文件、接口和其餘6大類20多種表引擎。其中每一種表引擎都有着各自的特色,用戶能夠根據實際業務場景的要求,選擇合適的表引擎使用。
一般而言,一個通用系統意味着更普遍的適用性,可以適應更多的場景。但通用的另外一種解釋是平庸,由於它沒法在全部場景內都作到極致。
在軟件的世界中,並不會存在一個可以適用任何場景的通用系統,爲了突出某項特性,勢必會在別處有所取捨。其實世間萬物都遵循着這樣的道理,就像信天翁和蜂鳥,雖然都屬於鳥類,但它們各自的特色卻鑄就了徹底不一樣的體貌特徵。信天翁擅長遠距離飛行,環繞地球一週只須要1至2個月的時間。由於它可以長時間處於滑行狀態,5天才須要扇動一次翅膀,心率可以保持在每分鐘100至200次之間。而蜂鳥可以垂直懸停飛行,每秒能夠揮動翅膀70~100次,飛行時的心率可以達到每分鐘1000次。若是用數據庫的場景類比信天翁和蜂鳥的特色,那麼信天翁表明的多是使用普通硬件就能實現高性能的設計思路,數據按粗粒度處理,經過批處理的方式執行;而蜂鳥表明的多是按細粒度處理數據的設計思路,須要高性能硬件的支持。
將表引擎獨立設計的好處是顯而易見的,經過特定的表引擎支撐特定的場景,十分靈活。對於簡單的場景,可直接使用簡單的引擎下降成本,而複雜的場景也有合適的選擇。
ClickHouse幾乎具有現代化高性能數據庫的全部典型特徵,對於能夠提高性能的手段可謂是一一用盡,對於多線程和分佈式這類被普遍使用的技術,天然更是不在話下。
若是說向量化執行是經過數據級並行的方式提高了性能,那麼多線程處理就是經過線程級並行的方式實現了性能的提高。相比基於底層硬件實現的向量化執行SIMD,線程級並行一般由更高層次的軟件層面控制。現代計算機系統早已普及了多處理器架構,因此現今市面上的服務器都具有良好的多核心多線程處理能力。因爲SIMD不適合用於帶有較多分支判斷的場景,ClickHouse也大量使用了多線程技術以實現提速,以此和向量化執行造成互補。
若是一個籃子裝不下全部的雞蛋,那麼就多用幾個籃子來裝,這就是分佈式設計中分而治之的基本思想。同理,若是一臺服務器性能吃緊,那麼就利用多臺服務的資源協同處理。爲了實現這一目標,首先須要在數據層面實現數據的分佈式。由於在分佈式領域,存在一條金科玉律—計算移動比數據移動更加划算。在各服務器之間,經過網絡傳輸數據的成本是高昂的,因此相比移動數據,更爲聰明的作法是預先將數據分佈到各臺服務器,將數據的計算查詢直接下推到數據所在的服務器。ClickHouse在數據存取方面,既支持分區 ( 縱向擴展,利用多線程原理 ),也支持分片 ( 橫向擴展,利用分佈式原理 ),能夠說是將多線程和分佈式的技術應用到了極致。
HDFS、Spark、HBase和Elasticsearch這類分佈式系統,都採用了Master-Slave主從架構,由一個管控節點做爲Leader統籌全局。而ClickHouse則採用Multi-Master多主架構,集羣中的每一個節點角色對等,客戶端訪問任意一個節點都能獲得相同的效果。這種多主的架構有許多優點,例如對等的角色使系統架構變得更加簡單,不用再區分主控節點、數據節點和計算節點,集羣中的全部節點功能相同。因此它自然規避了單點故障的問題,很是適合用於多數據中心、異地多活的場景。
ClickHouse常常會被拿來與其餘的分析型數據庫做對比,好比Vertica、SparkSQL、Hive和Elasticsearch等,它與這些數據庫確實存在許多類似之處。例如,它們均可以支撐海量數據的查詢場景,都擁有分佈式架構,都支持列存、數據分片、計算下推等特性。這其實也側面說明了ClickHouse在設計上確實吸收了各路奇技淫巧。與其餘數據庫相比,ClickHouse也擁有明顯的優點。例如,Vertica這類商用軟件價格高昂;SparkSQL與Hive這類系統沒法保障90%的查詢在1秒內返回,在大數據量下的複雜查詢可能會須要分鐘級的響應時間;而Elasticsearch這類搜索引擎在處理億級數據聚合查詢時則顯得捉襟見肘。
正如ClickHouse的"廣告詞"所言,其餘的開源系統太慢,商用的系統太貴,只有Clickouse在成本與性能之間作到了良好平衡,即又快又開源。ClickHouse當之無愧地闡釋了"在線"二字的含義,即使是在複雜查詢的場景下,它也可以作到極快響應,且無須對數據進行任何預處理加工。
數據分片是將數據進行橫向切分,這是一種在面對海量數據的場景下,解決存儲和查詢瓶頸的有效手段,是一種分治思想的體現。ClickHouse支持分片,而分片則依賴集羣。每一個集羣由1到多個分片組成,而每一個分片則對應了ClickHouse的1個服務節點。分片的數量上限取決於節點數量 ( 1個分片只能對應1個服務節點 )。
ClickHouse並不像其餘分佈式系統那樣,擁有高度自動化的分片功能。ClickHouse提供了本地表 ( Local Table ) 與分佈式表 ( Distributed Table ) 的概念。一張本地表等同於一份數據的分片。而分佈式表自己不存儲任何數據,它是本地表的訪問代理,其做用相似分庫中間件。藉助分佈式表,可以代理訪問多個數據分片,從而實現分佈式查詢。
這種設計相似數據庫的分庫和分表,十分靈活。例如在業務系統上線的初期,數據體量並不高,此時數據表並不須要多個分片。因此使用單個節點的本地表 ( 單個數據分片 ) 便可知足業務需求,待到業務增加、數據量增大的時候,再經過新增數據分片的方式分流數據,並經過分佈式表實現分佈式查詢。這就比如一輛手動擋賽車,它將全部的選擇權都交到了使用者的手中。
關於ClickHouse的安裝,咱們在這裏再也不詳細展開,官網有詳細的文檔能夠參考。
咱們使用Java客戶端鏈接ClickHouse進行一些簡單的操做。首先Clickhouse 有兩種 JDBC 驅動實現:
一種是官方給出的
<dependency> <groupId>ru.yandex.clickhouse</groupId> <artifactId>clickhouse-jdbc</artifactId> <version>0.2.4</version> </dependency>
還有一種第三方提供的驅動:
<dependency> <groupId>com.github.housepower</groupId> <artifactId>clickhouse-native-jdbc</artifactId> <version>2.5.2</version> </dependency>
二者間的主要區別以下:
驅動類加載路徑不一樣,分別爲
ru.yandex.clickhouse.ClickHouseDriver 和 com.github.housepower.jdbc.ClickHouseDriver
默認鏈接端口不一樣,分別爲 8123 和 9000
鏈接協議不一樣,官方驅動使用 HTTP 協議,而三方驅動使用 TCP 協議
須要注意的是,兩種驅動不可共用,同個項目中只能選擇其中一種驅動。
Class.forName("com.github.housepower.jdbc.ClickHouseDriver"); Connection connection = DriverManager.getConnection("jdbc:clickhouse://192.168.60.131:9000"); Statement statement = connection.createStatement(); statement.executeQuery("create table test.example(day Date, name String, age UInt8) Engine=Log"); PreparedStatement pstmt = connection.prepareStatement("insert into test.example values(?, ?, ?)"); // insert 10 records for (int i = 0; i < 10; i++) { pstmt.setDate(1, new Date(System.currentTimeMillis())); pstmt.setString(2, "panda_" + (i + 1)); pstmt.setInt(3, 18); pstmt.addBatch(); } pstmt.executeBatch(); Statement statement = connection.createStatement(); String sql = "select * from test.jdbc_example"; ResultSet rs = statement.executeQuery(sql); while (rs.next()) { // ResultSet 的下標值從 1 開始,不可以使用 0,不然越界,報 ArrayIndexOutOfBoundsException 異常 System.out.println(rs.getDate(1) + ", " + rs.getString(2) + ", " + rs.getInt(3)); }
經過 clickhouse-client 命令行界面查看錶狀況:
ck-master :) show tables; SHOW TABLES ┌─name─────────┐ │ hits │ │ jdbc_example │ └──────────────┘ ck-master :) select * from example; SELECT * FROM jdbc_example ┌────────day─┬─name─────┬─age─┐ │ 2019-04-25 │ panda_1 │ 18 │ │ 2019-04-25 │ panda_2 │ 18 │ │ 2019-04-25 │ panda_3 │ 18 │ │ 2019-04-25 │ panda_4 │ 18 │ │ 2019-04-25 │ panda_5 │ 18 │ │ 2019-04-25 │ panda_6 │ 18 │ │ 2019-04-25 │ panda_7 │ 18 │ │ 2019-04-25 │ panda_8 │ 18 │ │ 2019-04-25 │ panda_9 │ 18 │ │ 2019-04-25 │ panda_10 │ 18 │ └────────────┴──────────┴─────┘
從2019年起,已經有不少大廠開始在生產環境使用ClickHouse,小編在這裏根據各大公司使用狀況做了一些總結,適用場景、方案、優化等等。
下圖是攜程實際應用ClickHouse的架構圖,底層數據大部分是離線的,一部分是實時的,離線數據如今大概有將近 3000 多個 job 天天都是把數據從 HIVE 拉到 ClickHouse 裏面去,實時數據主要是接外部數據,而後批量寫到 ClickHouse 裏面。數據智能平臺 80%以上的數據都在 ClickHouse 上面。
同時,攜程還存在全量數據同步和增量數據同步的場景。
全量數據同步的流程流程以下圖:
QQ音樂大數據團隊基於ClickHouse+Superset等基礎組件,結合騰訊雲EMR產品的雲端能力,搭建起高可用、低延遲的實時OLAP分析計算可視化平臺。
集羣日均新增萬億數據,規模達到上萬核CPU,PB級數據量。總體實現秒級的實時數據分析、提取、下鑽、監控數據基礎服務,大大提升了大數據分析與處理的工做效率。
經過OLAP分析平臺,極大下降了探索數據的門檻,作到全民BI,全民數據服務,實現了實時PV、UV、營收、用戶圈層、熱門歌曲等各種指標高效分析,全鏈路數據秒級分析定位,增強數據上報規範,造成一個良好的正循環。
面對上萬核集羣規模、PB級的數據量,通過QQ音樂大數據團隊和騰訊雲EMR雙方技術團隊無數次技術架構升級優化,性能優化,逐步造成高可用、高性能、高安全的OLAP計算分析平臺。
(1)基於SSD盤的ZooKeeper
ClickHouse依賴於ZooKeeper實現分佈式系統的協調工做,在ClickHouse併發寫入量較大時,ZooKeeper對元數據存儲處理不及時,會致使ClickHouse副本間同步出現延遲,下降集羣總體性能。
解決方案:採用SSD盤的ZooKeeper大幅提升IO的性能,在表個數小於100,數據量級在TB級別時,也可採用HDD盤,其餘狀況都建議採用SSD盤。
(2)數據寫入一致性
數據在寫入ClickHouse失敗重試後內容出現重複,致使了不一樣系統,如Hive離線數倉中分析結果,與ClickHouse集羣中運算結果不一致。
解決方案:基於統一全局的負載均衡調度策略,完成數據失敗後仍然可寫入同一Shard,實現數據冪等寫入,從而保證在ClickHouse中數據一致性。
(3)實時離線數據寫入
ClickHouse數據主要來自實時流水上報數據和離線數據中間分析結果數據,如何在架構中完成上萬億基本數據的高效安全寫入,是一個巨大的挑戰。
解決方案:基於Tube消息隊列,完成統一數據的分發消費,基於上述的一致性策略實現數據冪同步,作到實時和離線數據的高效寫入。
(4)表分區數優化
部分離線數據倉庫採用按小時落地分區,若是採用原始的小時分區更新同步,會形成ClickHouse中Select查詢打開大量文件及文件描述符,進而致使性能低下。
解決方案:ClickHouse官方也建議,表分區的數量建議不超過10000,上述的數據同步架構完成小時分區轉換爲天分區,同時程序中完成數據冪等消費。
(5)讀/寫分離架構
頻繁的寫動做,會消耗大量CPU/內存/網卡資源,後臺合併線程得不到有效資源,下降Merge Parts速度,MergeTree構建不及時,進而影響讀取效率,致使集羣性能下降。
解決方案:ClickHouse臨時節點預先完成數據分區文件構建,動態加載到線上服務集羣,緩解ClickHouse在大量併發寫場景下的性能問題,實現高效的讀/寫分離架構,具體步驟和架構以下:
a)利用K8S的彈性構建部署能力,構建臨時ClickHouse節點,數據寫入該節點完成數據的Merge、排序等構建工做;
b)構建完成數據按MergeTree結構關聯至正式業務集羣。
固然對一些小數據量的同步寫入,可採用10000條以上批量的寫入。
(6)跨表查詢本地化
在ClickHouse集羣中跨表進行Select查詢時,採用Global IN/Global Join語句性能較爲低下。分析緣由,是在此類操做會生成臨時表,並跨設備同步該表,致使查詢速度慢。
解決方案:採用一致性hash,將相同主鍵數據寫入同一個數據分片,在本地local表完成跨表聯合查詢,數據均來自於本地存儲,從而提升查詢速度。
這種優化方案也有必定的潛在問題,目前ClickHouse尚不提供數據的Reshard能力,當Shard所存儲主鍵數據量持續增長,達到磁盤容量上限須要分拆時,目前只能根據原始數據再次重建CK集羣,有較高的成本。
ClickHouse從進入大衆視野到開始普遍應用實踐並不久,ClickHouse社區也在飛速發展中。ClickHouse仍然年輕,雖然在某些方面存在不足,但極致性能的存儲引擎,使得ClickHouse成爲一個很是優秀的存儲底座。