HBase 在滴滴出行的應用場景和最佳實踐
1.背景
**
1.1 對接業務型別**
HBase 是建立在 Hadoop 生態之上的 Database,源生對離線任務支援友好,又因為 LSM 樹是一個優秀的高吞吐資料庫結構,所以同時也對接了很多線上業務。 線上業務對訪問延遲敏感,並且訪問趨向於隨機,如訂單、客服軌跡查詢。離線 業務通常是數倉的定時大批量處理任務,對一段時間內的資料進行處理併產出結果,對任務完成的時間要求不是非常敏感,並且處理邏輯複雜,如天級別報表、 安全和使用者行為分析、模型訓練等。
1.2 多語言支援
HBase 提供了多語言解決方案,並且由於滴滴各業務線 RD 所使用的開發語言各 有偏好,所以多語言支援對於 HBase 在滴滴內部的發展是至關重要的一部分。我 們對使用者提供了多種語言的訪問方式:HBase Java native API、Thrift Server(主 要應用於 C++、PHP、Python)、JAVA JDBC(Phoenix JDBC)、Phoenix QueryServer (Phoenix 對外提供的多語言解決方案)、MapReduce Job(Htable/Hfile Input)、 Spark Job、Streaming 等。
**
1.3 資料型別**
HBase 在滴滴主要存放了以下四種資料型別:
- 統計結果、報表類資料:主要是運營、運力情況、收入等結果,通常需要配合 Phoenix 進行 SQL 查詢。資料量較小,對查詢的靈活性要求高,延遲要求一般。
- 原始事實類資料:如訂單、司機乘客的 GPS 軌跡、日誌等,主要用作線上和離線的資料供給。資料量大,對一致性和可用性要求高,延遲敏感,實時寫入,單點或批量查詢。
- 中間結果資料:指模型訓練所需要的資料等。資料量大,可用性和一致性要求一般,對批量查詢時的吞吐量要求高。
- 線上系統的備份資料:使用者把原始資料存在了其他關係資料庫或檔案服務, 把 HBase 作為一個異地容災的方案。
2. 使用場景介紹
2.1 場景一:訂單事件
這份資料使用過滴滴產品的使用者應該都接觸過,就是 App 上的歷史訂單。近期 訂單的查詢會落在 Redis,超過一定時間範圍或者當 Redis 不可用時,查詢會落在 HBase 上。業務方的需求如下:
- 線上查詢訂單生命週期的各個狀態,包括 status、event_type、order_detail 等資訊。主要的查詢來自於客服系統。
- 線上歷史訂單詳情查詢。上層會有 Redis 來儲存近期的訂單,當 Redis 不可用或者查詢範圍超出 Redis,查詢會直接落到 HBase。
- 離線對訂單的狀態進行分析。
- 寫入滿足每秒 10K 的事件,讀取滿足每秒 1K 的事件,資料要求在 5s 內可用。
按照這些要求,我們對 Rowkey 做出了下面的設計,都是很典型的 scan 場景。
訂單狀態表
Rowkey:reverse(order_id) + (MAX_LONG - TS) Columns:該訂單各種狀態
訂單歷史表
Rowkey:reverse(passenger_id | driver_id) + (MAX_LONG - TS) Columns:使用者在時間範圍內的訂單及其他資訊
2.2 場景二:司機乘客軌跡
這也是一份滴滴使用者關係密切的資料,線上使用者、滴滴的各個業務線和分析人員都會使用。舉幾個使用場景上的例子:使用者檢視歷史訂單時,地圖上顯示所經過的路線;發生司乘糾紛,客服呼叫訂單軌跡復現場景;地圖部門使用者分析道路擁堵情況。
使用者們提出的需求:
- 滿足 App 使用者或者後端分析人員的實時或準實時軌跡座標查詢;
- 滿足離線大規模的軌跡分析;
- 滿足給出一個指定的地理範圍,取出範圍內所有使用者的軌跡或範圍內出現過的使用者。
其中,關於第三個需求,地理位置查詢,我們知道 MongoDB 對於這種地理索引有源生的支援,但是在滴滴這種量級的情況下可能會發生儲存瓶頸,HBase 儲存 和擴充套件性上沒有壓力但是沒有內建類MongoDB 地理位置索引的功能,沒有就需要我們自己實現。通過調研,瞭解到關於地理索引有一套比較通用的 GeohHash 演算法 。
GeoHash 是將二維的經緯度轉換成字串,每一個字串代表了某一矩形區域。 也就是說,這個矩形區域內所有的點(經緯度座標)都共享相同的 GeoHash 字串,比如說我在悠唐酒店,我的一個朋友在旁邊的悠唐購物廣場,我們的經緯 度點會得到相同的 GeoHash 串。這樣既可以保護隱私(只表示大概區域位置而 不是具體的點),又比較容易做快取。
但是我們要查詢的範圍和 GeohHash 塊可能不會完全重合。以圓形為例,查詢時會出現如圖 4 所示的一半在 GeoHash 塊內,一半在外面的情況(如 A、B、C、 D、E、F、G 等點)。這種情況就需要對 GeoHash 塊內每個真實的 GPS 點進行第 二次的過濾,通過原始的 GPS 點和圓心之間的距離,過濾掉不符合查詢條件的資料。
最後依據這個原理,把 GeoHash 和其他一些需要被索引的維度拼裝成 Rowkey, 真實的 GPS 點為 Value,在這個基礎上封裝成客戶端,並且在客戶端內部對查詢 邏輯和查詢策略做出速度上的大幅優化,這樣就把 HBase 變成了一個 MongoDB 一樣支援地理位置索引的資料庫。如果查詢範圍非常大(比如進行省級別的分析), 還額外提供了 MR 的獲取資料的入口。
兩種查詢場景的 Rowkey 設計如下:
- 單個使用者按訂單或時間段查詢: reverse(user_id) + (Integer.MAX_LONG- TS/1000)
- 給定範圍內的軌跡查詢:reverse(geohash) + ts/1000 + user_id
2.3 場景三:ETA
ETA 是指每次選好起始和目的地後,提示出的預估時間和價格。提示的預估到達 時間和價格,最初版本是離線方式執行,後來改版通過 HBase 實現實時效果,把 HBase 當成一個 KeyValue 快取,帶來了減少訓練時間、可多城市並行、減少人工干預的好處。
整個 ETA 的過程如下:
- 模型訓練通過 Spark Job,每 30 分鐘對各個城市訓練一次;
- 模型訓練第一階段,在 5 分鐘內,按照設定條件從 HBase 讀取所有城市資料;
- 模型訓練第二階段在 25 分鐘內完成 ETA 的計算;
- HBase 中的資料每隔一段時間會持久化至 HDFS 中,供新模型測試和新的特徵提取。
Rowkey:salting+cited+type0+type1+type2+TS
Column:order, feature
**
2.4 場景四:監控工具 DCM**
用於監控 Hadoop 叢集的資源使用(Namenode,Yarn container 使用等),關係 資料庫在時間維度過程以後會產生各種效能問題,同時我們又希望可以通過 SQL 做一些分析查詢,所以使用 Phoenix,使用採集程式定時錄入資料,生產成報表, 存入 HBase,可以在秒級別返回查詢結果,最後在前端做展示。
圖 7、圖 8、圖 9 是幾張監控工具的使用者 UI,數字相關的部分做了模糊處理。
3. 滴滴在 HBase 對多租戶的管理
我們認為單叢集多租戶是最高效和節省精力的方案,但是由於 HBase 對多租戶基本沒有管理,使用上會遇到很多問題:在使用者方面比如對資源使用情況不做分 析、儲存總量發生變化後不做調整和通知、專案上線下線沒有計劃、想要最多的 資源和許可權等;我們平臺管理者也會遇到比如線上溝通難以理解使用者的業務、對 每個接入 HBase 的專案狀態不清楚、不能判斷出使用者的需求是否合理、多租戶在 叢集上發生資源競爭、問題定位和排查時間長等。
針對這些問題,我們開發了 DHS 系統(Didi HBase Service)進行專案管理,並且在 HBase 上通過 Namespace、RS Group 等技術來分割使用者的資源、資料和權 限。通過計算開銷並計費的方法來管控資源分配。
DHS 主要有下面幾個模組和功能:
- 專案生命週期管理:包括立項、資源預估和申請、專案需求調整、需求討論; 2. 使用者管理:許可權管理,專案審批;
- 叢集資源管理;
- 表級別的使用情況監控:主要是讀寫監控、memstore、blockcache、locality。
當用戶有使用 HBase 儲存的需求,我們會讓使用者在 DHS 上註冊專案。介紹業務 的場景和產品相關的細節,以及是否有高 SLA 要求。
之後是新建表以及對錶效能需求預估,我們要求使用者對自己要使用的資源有一個準確的預估。如果使用者難以估計,我們會以線上或者線下討論的方式與使用者討論 幫助確定這些資訊。然後會生成專案概覽頁面,方便管理員和使用者進行專案進展的跟蹤。
HBase 自帶的 jxm 資訊會彙總到 Region 和 RegionServer 級別的資料,管理員會 經常用到,但是使用者卻很少關注這個級別。根據這種情況我們開發了 HBase 表級別的監控,並且會有許可權控制,讓業務 RD 只能看到和自己相關的表,清楚自己專案表的吞吐及儲存佔用情況。
通過 DHS 讓使用者明確自己使用資源情況的基礎之上,我們使用了 RS Group 技術,把一個叢集分成多個邏輯子叢集,可以讓使用者選擇獨佔或者共享資源。共享和獨佔各有自己的優缺點,如表 1。
根據以上的情況,我們在資源分配上會根據業務的特性來選擇不同方案:
- 對於訪問延遲要求低、訪問量小、可用性要求低、備份或者測試階段的資料: 使用共享資源池;
- 對於延遲敏感、吞吐要求高、高峰時段訪問量大、可用性要求高、線上業務: 讓其獨佔一定機器數量構成的 RegionServer Group 資源,並且按使用者預估 的資源量,額外給出 20%~30%的餘量。
最後我們會根據使用者對資源的使用,定期計算開銷並向用戶發出賬單。
4. RS Group
RegionServer Group,實現細節可以參照 HBase HBASE-6721 這個 Patch。滴滴在這個基礎上作了一些分配策略上的優化,以便適合滴滴業務場景的修改。RS Group 簡單概括是指通過分配一批指定的 RegionServer 列表,成為一個 RS Group, 每個 Group 可以按需掛載不同的表,並且當 Group 內的表發生異常後,Region 不會遷移到其他的 Group。這樣,每個 Group 就相當於一個邏輯上的子叢集,通 過這種方式達到資源隔離的效果,降低管理成本,不必為每個高 SLA 的業務線單獨搭叢集。
5. 總結
在滴滴推廣和實踐 HBase 的工作中,我們認為至關重要的兩點是幫助使用者做出 良好的表結構設計和資源的控制。有了這兩個前提之後,後續出現問題的概率會大大降低。良好的表結構設計需要使用者對 HBase 的實現有一個清晰的認識,大多 數業務使用者把更多精力放在了業務邏輯上,對架構實現知之甚少,這就需要平臺管理者去不斷幫助和引導,有了好的開端和成功案例後,通過這些使用者再去向其 他的業務方推廣。資源隔離控制則幫助我們有效減少叢集的數量,降低運維成本, 讓平臺管理者從多叢集無止盡的管理工作中解放出來,將更多精力投入到元件社群跟進和平臺管理系統的研發工作中,使業務和平臺都進入一個良性迴圈,提升使用者的使用體驗,更好地支援公司業務的發展。