上海久耶基於HBase實時數倉探索實踐

weixin_33763244發表於2019-04-06

本文根據上海久耶大資料研發工程師武基鵬在中國HBase技術社群第四屆MeetUp上海站中分享的《基於HBase實時數倉探索實踐》編輯整理而成。

文章從六個方面介紹,首先是久耶第一代離線數倉以及第二代實時數倉。接下來介紹下公司業務場景和業務開發,基於 HBase 的開發流程,然後公司CDH叢集調優監控,最後分享兩個生產案例。

\"\"

第一代離線數倉是在去年三月份上線,主要是基於 OMS 和 WMS,由於分庫分表,大約有十幾個庫。前期通過 SQOOP 進行資料抽取,後來由於 SQOOP 的一些問題採用了阿里開源的 DataX,時間粒度使用指令碼排程實現, T+1 模式抽取到 Hive。分析時採用Apache的Kylin,將各個指標計算結果資料直接存入HBase 中,最初數倉的是用於各個部門業務指標的Dashboard,用的是Superset(只能定製化),後面也用了Saiku(支援上鑽下鑽,動態需求指標更多)。離線數倉六個月就被淘汰了,因為離線數倉有個問題,業務部分要查詢資料指標,但是時間粒度是昨天的,業務部分需要看當天一段時間內的資料,離線是無法滿足。

\"\"

接下來在另一個叢集構建實時數倉,其選型主要有兩個,第一個是實時,實時採集利用 Maxwell,直接採集公司資料庫 MySQL,將資料直接以 json 格式傳送到 Kafka叢集,數倉儲存選型是 HBase。

為什麼選擇 Maxwell 呢?

  1. 它能夠使用“select * from Table”進行 bootstrapping 初始化資料,在大資料構建時可以利用 Maxwell 進行全表掃描,這句 SQL 會自動觸發 Maxwell 某個執行緒進行資料拉取,將錶的歷史資料全部重新整理過去。

  2. Maxwell支援斷點還原功能,大資料平臺架構不光考慮到高可靠、高效能,也要保證資料零丟失,它支援MySQL的binlog檔案的pos點記錄進行資料還原,這是當初選擇最重要的原因。

  3. Maxwell將資料從MySQL傳送到Kafka,Kafka是分割槽的,如何保證全域性有序是個問題。
    它能保證這個特性,引數支援 database, table, primary key, or column選擇,
    將資料按照引數選擇傳送到某個分割槽。
    比如一條業務資料在業務系統先做insert再做update再做delete記錄,Kafka 會將這三條binlog資料傳送到三個分割槽,key值為空,在使用SparkStreaming消費時可能會以 delete、update、insert 順序,會造成資料紊亂。我們希望將這些特徵資料傳送到 Kafka一個分割槽,而Kafka 每個分割槽本身就是支援有序的。生產上,我們選擇primary key。

  4. 當業務資料的表結構需要升級,如加索引、加欄位,可以通過Maxwell捕獲到alert語句進行解析,同步更新到Phoenix表(HBase)中。

基於這四點主要特性需求,選擇了Maxwell,沒有選擇當前其他開源產品。

\"\"

接下來講一下為什麼選擇 HBase 而不選擇其他大資料元件?

  1. HBase 是分散式、可縮的;
  2. 隨機的讀和寫;
  3. HBase 支援百萬列。

更多的好處就不過多複述。

第三個介紹下為什麼要選擇Phoenix呢?

  1. HBase進行put資料,scan查詢、程式碼開發比較吃力,不優雅,而Phoenix是支援SQL。
  2. 我們構建的表是鹽表,能夠解決熱點問題,避免一個節點很繁忙另一個節點很閒。
  3. Phoenix支援二級索引,由於表是鹽表(分割槽),索引也是分割槽的。
  4. 支援Spark,有效的ETL敏捷開發。
    基於這四點主要特性需求,選擇了Phoenix,而不用專注於底層HBase,當成黑盒。(當然底層的Linux、HDFS、HBase也需要調優,穩定)

\"\"

\"\"

上圖是實時數倉架構圖,主要的儲存層還是以 HBase 為主。第一層業務系統資料庫在阿里雲平臺上,有 OMS、WMSReport DB 是 OMS 和 WMS 的合併從庫。使用Maxwell,其支援白名單和黑名單。業務平臺的表可能有兩三百個,大資料平臺的計算可能只需要 100 多個,可以新增白名單,有些表的資料就可以不用過來了。這些資料通過 Json 傳送到Kafka,然後通過 Spark Streaming 去消費 Kafka,通過 JDBC 寫入 HBase。(效能不低,現在我們生產上有反壓機制控制,3S一個批次可以寫最大6W資料,批次不堆積,不會有雪崩效應。要考慮資料獲取,處理,寫出去,所以3S是一個經典經驗值。)

表是通過Phoenix SQL語句建立,我們真正不關心底層HBase。就像操作MySQL一樣即可。同時會將計算結果儲存到Redis(雙十一實時大屏),也會將資料寫入ES裡面(久耶慧策IDSS,釘釘應用)。中間一層就是業務開發,如SparkStreaming、SparkSQl(現在也有Flink),也用 Python和R去分析挖掘。排程平臺起先用的是Azkaban,然後Airflow,最後用的是Rundeck(易用穩定主要選擇)。上圖藍色是實時大屏,紅色是全球倉庫指標,大約有四十幾個倉庫。運營人員是直接Saiku,將Phoenix jar包整合進去,Saiku支援上鑽下鑽,運營人員依據自己的需求去拿行和列資料,Saiku通過Phoenix組裝 SQL 語句查詢結果資料。也用到 zeppelin,這是 Spark 互動式開發必須用到的。

接下來講一下資料倉儲,首先是模型建設,第一層是基礎表,在Phoenix中建立與MySQL一樣的表。在基礎表的基礎上構建事實表(訂單事實發生的表)和維度表(如中國有多少省多少市等更新不是很大的表),依據事實表和維度表進行代開發,構建領域表,就是依據業務需求得出的結果存到領域表。資料校驗是通過資料量比對,起先是在從庫時做觸發器,但是 MySQL從庫觸發器不支援生效。通過改造Phoenix程式碼將資料寫入 Redis,增加加一刪除減一,MySQL 資料和 HBase 資料是一天卡一天對比。當不相等直接呼叫shell指令碼進行該表昨天整天資料重新整理同步(效能很高),然後調指令碼修復第二層第三層資料(凌晨排程,至關重要)。當前只採用 OMS、WMS 的庫,業務的QPS處於2000,1條資料: 平均60列,495b位元組。(現在我們已經對接13條業務指標資料同步,到大資料平臺)

\"\"

業務場景開始是業務報表開發,有客訴妥投、ABC訂單、商業季度等。也提供一個BI自助分析,第三個就是雙十一大屏和龍虎榜,同時使用了BMS系統,是一個商業結算系統。第五個是今年做的領導層和客戶層的慧策,商業決策分析。

業務開發套路就是依據業務需求將資料存在那些表裡面,需要將構建表的語句提取出來構建Phoenix Table,然後Kafka+Spark Streaming+Phoenix進行資料的插入。接著就是Spark開發讀和寫,我們還利用了DBeaver。我們建表使用了聯合元件,由於公司叢集規模不是很高,regionServer是38臺,COMPRESSION 是使用SNAPPY,這是依據壓縮比、解壓效能。

\"\"

接下來是一個經典開發案例 Kafka+Spark Streaming+Phoenix,Phoenix 可以理解為 MySQL 架包的 JDBC。我們並沒有使用 Phoenix 的 Pool 池,官方也推薦使用正常 JDBC 檔案,因為JDBC 已經支援長連線,Kafka接收過來資料是Json格式,將其轉化為Phoenix的upsert語法和delete 語法,完成後就將連線關閉。(這個場景是做資料實時同步。當然也可以在foreachPartition進行常規資料ETL處理,這裡不過多敘述)

\"\"

\"\"

大資料平臺是通過 bootstrapping的全表掃描,其增量資料也是實時進入。業務程式碼開發首先將client jar包配置在pom 檔案。Phoenix+Spark 讀取有好幾種,選擇以上寫法原因有:首先其支援列裁剪,第二支援 where 條件,configuration 指的是Spark的HDFS的conf。

業務開發是多張表,Spark+Phoenix轉成df,接下來就和Phoenix和HBase無關。接下來就是對接 Spark 業務開發邏輯處理,最後結果集會回寫到HBase,還是通過 Phoenix 寫入,使用overwrite。HBase 沒有很好地視覺化工具,我們直接利用DBeaver工具,進行表及資料的各種建表、查詢等操作來。

\"\"

接下來介紹下叢集調優引數,分為六個方面:(1)Linux parameters、(2)HDFS parameters、(3)HBase parameters、(4)GC parameters、(5)Monitor、(6)Bug。控制程式碼數、檔案數、執行緒數這些都是要調,因為regionserver 在操作時需要 open file,處理時需要用到一些執行緒,一些系統都是架設在 Linux 上,因此叢集調優都需要調它。需要注意的是改完後需要檢查是否生效,立即生效是sysctl -p命令。Spark 開發需要將資料頻繁的寫入HBase中,HBase底層是HDFS,在寫入時就會出現問題,最後發現Linux 系統引數沒有調。

\"\"

在正常的 HBase 節點機器上,swap 是設定為 0,這並不是禁用 swap 而是其惰性是最大的。由於我們公司由於業務系統較多,吃的記憶體比較緊,因此設為 10,這樣可以使 job 慢一點但是不能掛,但是如果做實時就需要設定為 0。這個最終設定取決於你們自身業務環境,選擇自己需要的就好。如果做 CBH 的平臺部署必須要關閉大頁面。

接下來分享一個有意思的引數 HDFS Parameters,正常調優是CDH介面開啟、HBase 的配置引數tab頁開啟。主要調優是 timeout 和 handler 引數,將其幾倍放大,socket.timeout在HBase的 xml 檔案一定要部署,否則無法支援高效能寫操作。

\"\"

無法建立一個本地執行緒,丟擲oom錯誤。
當時datanode的記憶體配置是 8G,實際只使用1G,這個時候就要加上三個引數:

echo \u0026quot;kernel.threads-max=196605\u0026quot; \u0026gt;\u0026gt; /etc/sysctl.confecho \u0026quot;kernel.pid_max=196605\u0026quot; \u0026gt;\u0026gt; /etc/sysctl.confecho \u0026quot;vm.max_map_count=393210\u0026quot; \u0026gt;\u0026gt; /etc/sysctl.confsysctl -p  vi /etc/security/limits.conf* soft nofile 196605* hard nofile 196605* soft nproc 196605* hard nproc 196605

這其實是底層 Linux 丟擲的錯誤。
提醒一點 socket.timeout 引數不僅在 HDFS 中需要配置,在 HBase 中也需要配置。

GC引數調優是regionserver至關重要的配置,但是CDH配置,GC 預設垃圾選擇器是CMS,需要將其改為G1,如果需要配置可以去嘗試下,小米以前分享過。可以對引數進行除錯進行壓測調優,尤其大資料平臺開發必不可少如此。

\"\"

專案上線需要做監控,第一個就是 HBase 的讀和寫,綠色是寫,但是讀存在兩個波峰,因為我們的排程平臺以一個小時將所有 job 排程完。圖中 Y 軸是每秒的請求量,如果寫的沒有或者讀的波峰沒有規律,就有可能是叢集宕了。

第二個監控的指標是 FDS,就是 Regionserver 的檔案控制程式碼數,如果請求很多,控制程式碼數會很高,因為其底層依賴於 Linux,如果超過 Linux 設定值機器容易夯住下線,導致 CPU 不正常,這時需要後臺強制機器下線。然後需要監控 Zookeeper,監控的是 Zookeeper Open Connections,因為 HBase 進行操作需要開啟的連線,當業務場景為長服務,如 Spark streaming 一直執行,先前嘗試用 SparkSQL+Phoenix 做一個長服務,因為排程都是通過 shell 指令碼排程,在資源緊張時需要搶資源,在 submit 時需要申請資源(大約 30S),線上是不允許的。最後採用 Spark streaming+Spark SQL+Phoenix JDBC,Spark streaming 是實時的每隔一小時判斷進行資料處理(行業術語:空轉),這個時候 Zookeeper Open Connections 就隨著遞增趨勢上漲,當到 Connection 數(預設 500)CDH 會殺掉,說白了就是記憶體洩漏。後來打補丁,利用 PHOENIX-4319:Zookeeper connection should be closed immediately 解決問題。

\"\"

接下來講一下 Kafka 如何做監控,其實只需要上面一幅圖,上圖綠色線是讀 消費者,是藍色線是寫 生產者。Maxwell生產者寫到 Kafka 裡面,綠色是 Spark streaming 進行消費。這幅圖是實時同步架構,訊息沒有做積壓。但是為什麼綠色線會比藍色線高,原因是資料通過 Maxwell 傳送到 Kafka 時是一個 Json 資料,但是 Kafka 消費時需要額外加一些東西(來自哪個 topic、offset 是什麼等),如果兩條線走勢是一致的,說明訊息沒有堆積,及時消費,穩穩的。

Bug 方面,PHOENIX-4056:java.lang.IllegalArgumentException: Can not create a Path from an empty string,先前有問題採用降版本,目前已經解決,方案在社群裡有。SPARK-22968:java.lang.IllegalStateException: No current assignment for partition kssh-2,這個是SparkStreaming 讀Kafka時丟擲的錯誤,這個在Spark2.4.0有新的補丁。(各位道友,不要看看貴公司該架構有沒有,切記打補丁喲!)

接下來分享兩個案例,分為兩種,一種是 3 次 RIT,園區斷電機器掛掉出現 RIT。HBase 有個 WAL,資料基本不會丟,只需要將機器重啟。重啟過程會有一些 RIT 操作,如果 regionserver 掛了申請維護時間,嘗試重啟 regionserver 節點,如果不行重啟 HBase 叢集,這個時候需要看 HBase 的 master 的 active 的 log 日誌。還有一次是高併發記憶體不夠用,regionserver 掛掉,重啟後在 CDH 的 HBase 執行正常,但是在監控頁面 HBase 還是異常,這時候只需要將 CMS 的 serviceMonitor 重啟就 OK。第三次 RIT 事故 regionserver 掛掉,嘗試使用 HBCK 命令修復問題還是很多。最後通過日誌分析發現 Hlog 有問題,通過 HDFS 命令將檔案移到某個地方,重啟就 OK 了。丟失的資料通過 Maxwell 恢復,預估事故發生點,通過全表指定時間點掃描進行恢復,且要做資料量比對,行業中叫法:補數!

\"\"

接下來分享一個三支菸的故事,資料來源於阿里雲,自建機房需要通過 VPN 將資料拉倒本地機房。雙十一所有倉庫都在運作,MySQL機器扛不住導致延遲比較大,延遲約半個小時。(資料延時原因好幾種結合導致的。)

需要在 T2 將資料完全恢復,解決方案直接將 Maxwell 架設到阿里雲MySQL進行實時同步,資料進行[T1,T2)資料先刷到HBase,將 T1 到 T2 的資料進行 SparkSQL,將計算結果寫到 redis 裡面,作為基礎值。SparkStreaming 進行現場改,只判斷 T2 流進的資料才會將基礎值+T2以後的資料進行累積計算,實時 Job 跑了 15 分鐘資料就實時過來了,精準鏈路切換,不能丟資料,不能錯誤計算結果!(各位道友,當然現實現場發生的,比分享的還要精彩和詳細,各位可以看視訊版的或和我交流。)

作者介紹

武基鵬,上海久耶供應鏈管理有限公司大資料研發工程師。主要從事大資料平臺產品的技術工作;負責設計、構建和優化基於HDFS/HBase的儲存平臺架構;負責提升Hadoop/HBase等叢集的高可用性、高效能、高擴充套件特性;負責基於Spark開發及效能調優。

本文來自武基鵬在 DataFun 社群的演講,由 DataFun 編輯整理。

相關文章