Categories
程式開發

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行


億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 1

近年來,隨著大數據分析技術的普及和物聯網產業的興起,越來越多的企業開始重視海量數據的收集和分析處理活動,希望從龐大的數據資料中挖掘出高價值的信息和洞見。而在數據規模快速膨脹的同時,企業對數據處理平台的軟硬件基礎設施也提出了更高的要求,並在這一領域催生了很多高水平的前沿技術變革。

在這樣的趨勢下,由俄羅斯Yandex 開發的一款名為Clickhouse 的數據庫產品就在眾多競爭者中脫穎而出,憑藉十億乃至百億行的數據規模下依舊具備秒級返回能力的卓越性能,贏得了全球眾多大廠的青睞。 Clickhouse 究竟有怎樣的獨門絕技,如何做到如此強悍的性能表現,實踐中又是如何在主流雲平台上部署和優化的? 9 月22 日,來自京東智聯云云產品研發部的架構師王向飛老師做客InfoQ,介紹了Clickhouse 數據庫在京東智聯雲的落地應用與優化改進經歷,為想要深入了解Clickhouse 的小伙伴們送上了一堂乾貨滿滿的技術分享課程。

本文總結自王向飛老師的在線公開課:《Clickhouse 在京東智聯雲的大規模應用和架構改良》。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 2

根據數據庫處理的業務數據量,以及處理數據的不同方式,人們把數據庫分為OLTP 和OLAP 兩大類型。由俄羅斯Yandex 搜索引擎公司開發並開源的Clickhouse 數據庫,其初始定位就是Yandex 內部的分析型數據庫,符合OLAP 類型數據庫的實現特點。 Clickhouse 的性能超過了很多流行的商業數據庫,已經得到了包括CloudFlare、Spotify、阿里雲、騰訊雲、京東智聯雲、今日頭條、攜程等諸多頭部大廠的採用。

OLTP與OLAP

常見的Oracle、MySQL 等數據庫都屬於OLTP 類型,也就是On-Line Transaction Processing,聯機事務處理。 OLTP 數據庫處理請求和數據時對延遲要求很高,並且要保證數據的完整性和一致性。此類數據庫是面向最終客戶的,需要具備7×24 不間斷服務能力。

OLAP 的含義是聯機分析數據處理,這種數據庫需要存儲海量、但很少更新修改的數據,主要用於多維度歷史數據分析統計目的。出於這種需求,OLAP 數據庫需要確保足夠高的查詢效率,至少90% 的請求要在很短的時間內返回。

另一方面,OLAP 數據庫並不是直接面對最終客戶,而是更關注數據吞吐,要求海量數據盡快持久化,為業務決策、戰略定位和分析、個性化推薦等任務提供分析統計能力,所以這類數據庫中的查詢一般都是較低頻的。

Clickhouse 的關鍵特性:

列式存儲基於OLAP 數據庫的特點,Clickhouse 採用了基於列的數據存儲引擎。傳統的行式數據庫在存儲信息時,是在數據庫中按順序逐個記錄的。以用戶註冊信息為例,行式數據庫會將每個用戶的姓名、職業、年齡等數據依次記錄下來。當業務需要查找註冊用戶的職業或年齡分佈時,數據庫需要打開所有存儲用戶註冊信息的文件,遍歷全部數據行,依次挑出所有職業和年齡信息進行匯總。使用這種方式,查詢遍歷的數據往往遠大於所需的數據大小,對IO 能力會造成嚴重浪費。

相比之下,列式存儲會將數據分為多個屬性列,例如用戶註冊信息分為職業、年齡等多個屬性,並按這些屬性列分為多個文件分別存儲。這樣當查詢需要獲取其中某些屬性的數據時,只需查找對應文件即可完成,大大節約了IO 需求。

以一個包含1 億條數據的測試表為例,一個簡單的count 查詢在MySQL 上需要兩分多鐘,而在列式存儲的Clickhouse 數據庫上僅用不足1 秒就返回了結果。那麼,Clickhouse 具體都使用了哪些技術來實現如此高的效率提升呢?

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 3

B +樹vs合併樹

在深入研究Clickhouse 之前,我們首先以傳統的MySQL InnoDB 的存儲格式來做對比。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 4

從InnoDB 的邏輯結構圖可以看到,在InnoDB 中所有數據會被放在表空間內。表空間可以看作是InnoDB 的邏輯最高層,由多個段組成,段又分為數據段、索引段。數據生成時按順序寫入數據段,隨著數據記錄的增多,InnoDB 會將一些主鍵值放到索引段內以實現快速定位。

隨著數據量不斷增多,數據庫形成了名為B+Tree 的樹狀結構。這個樹有層級結構,會橫向生長,其查詢的複雜度取決於樹的高度。 B+Tree 的數據節點一般存儲主鍵值,根據主鍵查找時可以通過葉子節點大概定位數據頁,之後直接讀取數據頁即可。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 5

而Clickhouse 的數據架構類似關係型數據庫,其中包括了解析器,主要負責將SQL 語句通過詞法分析、語法分析等轉換成計算機可讀的抽象語法樹。另外還有優化器,邏輯優化負責優化抽象語法樹的邏輯,比如簡化一些長難運算表達式,做一些語義優化等。物理優化則負責生成可以直接執行的物理執行計劃,指導數據庫管理系統如何獲取數據表、如何進行數據join、排序等等。

Clickhouse 的物理執行計劃可認為是一個數據流圖,也就是數據的有向無環圖。在這個圖裡,數據從一個管道傳到另一個管道,也就是從一個操作符傳到另一個操作符。查詢執行器是用來執行計劃的引擎,它會從存儲引擎中取出數據,並返回給客戶端。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 6

如上圖,Clickhouse 在啟動時加載配置信息,然後根據不同的解析協議監聽不同的服務端口。客戶端發送來SQL 請求後,首先它會對SQL 進行語法解析,然後生成抽象語法樹,並進行一系列的邏輯優化、物理優化,生成執行計劃。接下來由不同的執行器根據SQL 請求來將執行計劃分發到本地或遠端的存儲引擎,從存儲引擎中取出數據。數據經過一系列的計算加工後返回給客戶端,客戶端就可以輸出緩衝區讀取查詢結果。

MergeTree 存儲過程

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 7

本例中,我們根據出生日期做一個數據分區,主鍵選用用戶的名字,並設置SETTINGS index_granularity=3。表建成後插入10 條記錄,分為2001 年3 月和2001 年2 月兩個數據區間。表建完、數據寫完以後,Clickhouse 默認會在數據文件存放路徑下建一個相應的表名:

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 8

這裡可以看到,10 條數據分了兩個文件夾來存儲。文件夾命名時,其第一部分是分區鍵,也就是出生日期;1_1(2_2)代表每個數據分區內數據塊最小塊和最大塊的編號。最後的數字0 代表合併層級。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 9

上圖是MergeTree 中對Data part 進行元數據管理的結構體。其中,partition id 代表數據所處的分區id;min block、max block 代表數據寫入的版本信息——用戶每次批量寫的數據都會生成一個Data part,同一批寫入的數據會被標記為唯一的block number。 MergeTree 存儲引擎後台會定期通過異步任務合併數據,且只會合併位於同一個數據分區內的數據,還要求min block 和max block 數據區間必須是連續非重合的。

第四個level 字段默認新插入的數據都是0,之後會隨著合併次數的增加在原來的基礎上依次增大。下面的mutation 字段在數據更正時使用。如果要進行數據的更正操作,Clickhouse 會默認給mutation 字段進行標記和更新。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 10

雖然測試數據只有一張表10 條數據,但它會在磁盤目錄上生成大量文件。具體來說,Clickhouse 默認每一個列生成一個文件,默認數據文件放在bin 文件裡。每一個數據分析目錄下生成一個count 文件,記錄分區裡有多少行數據。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 11

本例中,建表時設置的SETTINGS index_granularity 設為3。插完數據以後觀察主鍵索引,可以發現它會把主鍵以每3 條記錄為一個區間,將主鍵信息存儲在primary.idx 裡。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 12

結合前文例子來看數據全景。假設下面綠顏色的就是要寫入的一批數據,存放用戶的名字;假設每個名字佔用4 個字節,可以看到綠顏色上邊有一個granule,寫的是8192。指定granule 是8192 之後,數據在寫入時會放到一個具有緩衝區的OutPort 流中,按照一個granule 一個granule 來寫;寫完第一個granule,當發現這個緩衝區內數據大小超過64KB,這時就會把數據進行壓縮落盤,放在下邊的粉紅色文件塊裡。落數據塊時會先寫一個文件頭,文件頭由三部分組成,如上圖所示。

第二段8192 的數據,壓縮完之後數據塊可能比較長一些;可以發現,數據每次寫入就會產生兩個文件。一個是bin 文件,也就是壓縮後的數據文件。另一個文件就是主鍵index 文件。但這樣以來,在數據查詢時不知道數據究竟在數據文件裡的哪一塊,不知道該怎麼拆分bin 文件,如果把整個bin 文件都加載內存以後掃描,效率是會很差的。為了解決這個尷尬的問題Clickhouse 引入了mrk 文件。寫數據文件的時候會把bin 文件頭信息寫到mrk 文件裡。比如說第一塊數據寫完之後,會把起始位置、解壓縮後的位置、解壓縮前的位置放在mrk 這個文件塊裡, 作為一行記錄。查詢時直接根據主鍵index 記錄的偏移量找到對應的mrk 記錄的某段數據的起始位置,之後讀取數據即可。

MergeTree 也有一些異步任務處理,主要有三部分:首先是定期把一些有問題的、提交失敗的、或寫失敗的數據文件清理掉;然後是定期把一些比較瑣碎的插入語句生成的小文件塊合併為大的文件塊;還有偶爾有一些更正,例如數據的更新刪除生成的臨時文件,MergeTree 也會把對應的數據文件匯總成一個比較大的Part。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 13

智聯雲選擇K8s 部署的原因

京東智聯雲基於現有的雲平台部署Clickhouse 時,是基於K8s 團隊提供的強大運維調度平台來實現的。之所以選擇基於K8s 來部署有幾方面原因:

首先,K8s 可以屏蔽底層的環境差異,使用戶無需再具體關注主機網絡、存儲、API 接口等變化,只需將精力集中到數據庫管理開發任務上。其次,構建這個JCHDB 平台並不只是為京東智聯雲內部使用。這個平台構建完成後,不僅可以在公有云上給客戶提供服務,並且在私有化部署或者跨雲部署時,都可以完全不用對架構做任何修改直接部署。

智聯雲部署Clickhouse 的流程

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 14

這個operator 開發部署完畢,安裝到K8s 以後,K8s 就有了管理調度Clickhouse 狀態的能力。在它的外部會藉助helm 系統,將提前定義好的一些表單發送給K8s,由K8s 來根據表單裡定義的這些參數來創建需要的實例。

除了創建最基礎的Clickhouse,如果需要有復制關係引擎,它也會一同創建Zookeeper;同時為了豐富監控能力,便於DBA 進行服務器的運維監控,它還會創建一個Promethus,還有可視化的Grafana。這樣它就可以直接在VPC 里通過Grafana 來監控數據庫的運維狀態。

這個服務還會創建一個綁定headless service ip 地址的域名,用戶可以通過這個數據庫域名直接連到這一套Clickhouse 系統上。由上圖右可見,這個Pod 的底層存儲使用了京東的雲硬盤,它會在建Pod 時申請一個PVC 控制器,PVC 控制器會綁定京東雲硬盤。這樣就形成了計算與存儲分離的架構,可以進一步提升計算能力。

京東智聯雲目前在高性能、高可用和可擴展層面上都有自己的特色:

高性能方面,智聯雲採用最新一代的雲主機,CPU 最大可以支持64 核心,單個Pod 最大可以擴展到512G 內存。高可用方面,智聯雲借助K8s 調度管理平台,發現有Pod 不可用時K8s 會自動將這個Pod 剔除。同時平台會新建一個Pod,基於StatefulSet 機制將被刪除的Pod 所綁定的雲盤掛到新Pod 上。這樣如果有實例由於某些硬件原因出現問題,可以在分或秒級完成實例替換。可擴展方面,智聯雲基於雲主機、雲硬盤的一些基礎組件,提供了一些靈活的擴展接口,可以直接在原地擴容。智聯雲支持熱擴容,可以在不影響用戶使用的前提下,在分鐘級甚至秒級就可以完成CPU 數量、內存容量或磁盤空間的擴容。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 15

京東智聯雲還提供了完善的監控體系,可以幫助DBA 更好地觀察的數據庫的運行狀況。平台不但提供了service 級別的數據庫監控,同時還能把所有Pod 所使用的磁盤空間、CPU、內存都展示給用戶。有了這些信息,用戶可以更加直觀地觀察到每一個Pod 的壓力分佈情況,進而方便靈活地調整數據壓力,避免某個Pod 出現數據瓶頸。

根據這些監控的目標,用戶可以靈活地定義告警信息。智聯雲支持多維度數據告警,可以通過郵件、短信、微信等形式告警。

億級數據庫毫秒級查詢?看完這一篇,海量數據賦能你也行 16

Clickhouse 自身俱備強大的數據處理能力,還能很好地兼容SQL 語句。但在實際設計和使用過程中,不能僅僅把它當成一個傳統關係型數據庫的增強替代品,這樣可能會限制Clickhouse 的潛力發揮。企業需要對傳統的數據倉庫、設計理念,以及數據上下游的流轉方式做出改進,發揮想像力和創造力,更好地利用Clickhouse 的列式存儲、並行計算等數據能力,為數據業務創造更大價值。

京東智聯雲的Clickhouse 目前正在產品公測,歡迎大家使用。

點擊【閱讀原文“】獲取課程視頻