Categories
程式開發

知乎Hive Metastore 實踐:從MySQL 到TiDB


Apache Hive 是基於Apache Hadoop 的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並且提供了Hive SQL 進行查詢和分析,在離線數倉中被廣泛使用。

Hive Metastore 是Hive 的元信息管理工具,它提供了操作元數據的一系列接口,其後端存儲一般選用關係型數據庫如Derby、 MySQL 等。 現在很多除了Hive 之外計算框架都支持以Hive Metastore 為元數據中心來查詢底層Hadoop 生態的數據,比如Presto、Spark、Flink 等等。

在知乎,我們是將元信息存儲在MySQL 內的,隨著業務數據的不斷增長,MySQL 內已經出現單表數據量兩千多萬的情況,當用戶的任務出現Metastore 密集操作的情況時,往往會出現緩慢甚至超時的現象,極大影響了任務的穩定性。 長此以往,MySQL 在未來的某一天一定會不堪重負,因此優化Hive 的元數據庫勢在必行。

在去年,我們做過數據治理,Hive 表生命週期管理,定期去刪除元數據,期望能夠減少MySQL 的數據量,緩解元數據庫的壓力。 但是經過實踐,發現該方案有以下缺點:

1、數據的增長遠比刪除的要快,治標不治本;

2、在刪除超大分區表(分區數上百萬)的分區時,會對MySQL 造成一定的壓力,只能單線程去做,否則會影響其他正常的Hive 查詢,效率極其低下;

3、在知乎,元信息刪除是伴隨數據一起刪除的(刪除HDFS 過期數據,節約成本),Hive 的用戶可能存在建表不規範的情況,將分區路徑掛錯,導致誤刪數據。

因此,我們需要尋找新的技術方案來解決這個問題。

技術選型

已有方案

業內目前有兩種方案可供借鑒:

  1. 對MySQL 進行分庫分錶處理,將一台MySQL 的壓力分攤到MySQL 集群;

  2. 對Hive Metastore 進行Federation,採用多套Hive Metastore + MySQL 的架構,在Metastore 前方設置代理,按照一定的規則,對請求進行分發。

但是經過調研,我們發現兩種方案都有一定的缺陷:

  1. 對MySQL 進行分庫分錶,首先面臨的直接問題就是需要修改Metastore 操作MySQL 的接口,涉及到大量高風險的改動,後續對Hive 的升級也會更加複雜;
  2. 對Hive Metastore 進行Federation,儘管不需要對Metastore 進行任何改動,但是需要額外維護一套路由組件,並且對路由規則的設置需要仔細考慮,切分現有的MySQL 存儲到不同的MySQL 上,並且可能存在切分不均勻,導致各個子集群的負載不均衡的情況;
  3. 我們每天都會同步一份MySQL 的數據到Hive,用作數據治理,生命週期管理等,同步是利用內部的數據同步平台,如果採用上面兩種方案,數據同步平台也需要對同步邏輯做額外的處理。

最終方案

其實問題主要在於,當數據量增加時,MySQL 受限於單機性能,很難有較好的表現,而將單台MySQL 擴展為集群,複雜度將會呈幾何倍上升。 如果能夠找到一款兼容MySQL 協議的分佈式數據庫,就能完美解決這個問題。 因此,我們選擇了TiDB

TiDB 是PingCAP 開源的分佈式NewSQL 數據庫,它支持水平彈性擴展、ACID 事務、標準SQL、MySQL 語法和MySQL 協議,具有數據強一致的高可用特性,是一個不僅適合OLTP 場景還適OLAP 場景的混合數據庫。

選用TiDB 的理由如下:

  1. TiDB 完全兼容MySQL 的協議,經過測試,TiDB 支持Hive Metastore 對元數據庫的所有增刪改查操作, 使用起來不存在兼容性相關的問題。 因此,除了將MySQL 的數據原樣dump 到TiDB,幾乎沒有其他工作需要做;

  2. TiDB 由於其分佈式的架構,在大數據集的表現遠遠優於MySQL;

  3. TiDB 的可擴展性十分優秀,支持水平彈性擴展,不管是選用分庫分錶還是Federation,都可能會再次遇到瓶頸,屆時需要二次切分和擴容,TiDB 從根本上解決了這個問題;

  4. TiDB 在知乎已經得到了十分廣泛的應用,相關技術相對來說比較成熟,因此遷移風險可控。

Hive 架構

遷移前

知乎Hive Metastore 實踐:從MySQL 到TiDB 1

其中Zue 是知乎內部使用的可視化查詢界面。

遷移後

知乎Hive Metastore 實踐:從MySQL 到TiDB 2

在Hive 的元數據庫遷移到TiDB 了以後,架構幾乎沒有任何變化,只不過查詢的壓力由單台MySQL 節點分攤到了整個TiDB 集群,集群越大,查詢效率越高,性能提升越明顯。

遷移流程

  1. 將TiDB 作為MySQL 的從庫,實時同步數據;
  2. Metastore 縮容至1 個,防止多個Metastore 分別向MySQL 及TiDB 寫入,導致元數據不一致;
  3. 選取業務低峰期,主從切換,將主切為TiDB,重啟Metastore ;
  4. Metastore 擴容。
    此遷移過程對業務幾乎無感,成功上線。

運行概況

  1. 我們從Hive 層面對數據庫進行了測試,模擬業務高峰期,多並發對百萬分區級別的表增刪分區,所執行的Hive SQL 如下:
   ALTER TABLE '${table_name}' DROP IF EXISTS PARTITION(...);
   ALTER TABLE '${table_name}' ADD IF NOT EXISTS PARTITION(...);

花費時間從45s-75s 降低到了10s 以下。

  1. 我們從元數據庫層面測試了一些Metastore 提交的SQL,尤其是那些會造成元數據庫壓力巨大的SQL,例如:
SELECT `A0`.`PART_NAME`,`A0`.`PART_NAME` AS `NUCORDER0` FROM `PARTITIONS` `A0` LEFT OUTER JOIN `TBLS` `B0` ON `A0`.`TBL_ID` = `B0`.`TBL_ID` LEFT OUTER JOIN `DBS` `C0` ON `B0`.`DB_ID` = `C0`.`DB_ID` WHERE `C0`.`NAME` = '${database_name}' AND `B0`.`TBL_NAME` = '${table_name}' ORDER BY `NUCORDER0`

當某個Hive 表的分區數量十分巨大時,這條SQL 會給元數據庫造成相當大的負擔。 遷移前,此類SQL 在MySQL 運行時間約為30s – 40s,遷移後,在TiDB 運行僅需6s – 7s,提升相當明顯。

  1. 數據同步平台上的Hive 元數據庫內的SDS 表的同步任務時間從90s 降低到15s。

展望

在Hive Metastore 的場景下,我們已經感受到了TiDB 在大數據應用場景下的魅力。 後續我們希望TiDB 能夠成為跨數據中心的服務,通過數據副本的跨機房部署,打通離線與在線,讓離線場景能夠在對在線服務無壓力的情況下為數據提供實時的ETL 能力,解決離線ETL 任務實時性差的問題。 為此,我們正在開發TiBigData (https://github.com/pingcap-incubator/TiBigData)。

目前其作為PingCAP Incubator 的孵化項目。 由來自知乎的TiKV Maintainer 孫曉光發起。 PingCAP Incubator 旨在梳理一套相對完整的TiDB 生態開源項目孵化體系,將關於TiDB 開源生態的想法與實際生產環境中的需求相關聯,通過開源項目協作方式,共同將想法落地。 力求想法項目化。 從「我有一個想法」到「項目順利畢業」,PingCAP 提供一系列的資源支持,確保所有項目孵化的流程都有章可循,同時結合項目不同特徵及孵化目的,將項目劃分為Feature 類和Project 類,針對性地給出孵化流程建議。 PingCAP Incubator 中的項目有:TiDB Dashboard、TiUP、TinyKV,TiDB Wasm 等。

完整項目請查看:
https://github.com/pingcap-incubator

PingCAP Incubator 完整文檔參考:
https://github.com/pingcap/community/tree/master/incubator