在各行各業紛紛結合自身需求,加快自主改造和研發腳步的當下,涌現出許多值得學習借鑑的優秀項目。本期【自研出圈】將詳述光大銀行首個獨立研發的基礎軟件Pharos,如何從HBase二級索引出發,提高多條件複雜查詢的性能,拓展HBase的數據使用模式,應對海量數據低延時複雜查詢。程序員
做者介紹web
王磊(Ivan),光大銀行科技部數據領域架構師,曾任職於IBM全球諮詢服務部從事技術諮詢工做,具備十餘年數據領域研發及諮詢經驗。目前負責全行數據領域系統的平常架構管理、重點系統架構設計及內部研發等工做,對分佈式數據庫、Hadoop等基礎架構研究有濃厚興趣。我的公衆號:金融數士。數據庫
NoSQL興起無疑是大數據時代的標誌性事件,創新者們不斷打破關係型數據庫「一種存儲模式解決全部問題」的思路,發明了不少不一樣的產品應對細分的數據訪問模式,它們提供了更好的服務特性,好比低延時、高併發等等。HBase是其中極具表明性的產品,做爲Hadoop生態體系的明星產品,時至今日已在不少企業獲得普遍應用。
緩存
NoSQL這種爲特定的數據使用模式設計存儲系統的思路,收穫了性能的大幅提高,但隨着存儲數據量的激增,對解決方案總體性價比的滿意度卻在不斷走低。畢竟,相較幾個TB和數百TB,存儲成本對用戶的衝擊力是不一樣的,人們老是不滿於線性增加的成本,但願能花更少的錢作更多的事。安全
經過適度拓展數據訪問模式提高性價比,成爲業內不少技術方案追求的目標。微信
光大銀行是金融行業中較早引入HBase的,通過若干年建設已經積累了大量數據。若是僅是爲了知足不一樣條件的查詢,就copy一個同等規模的集羣,是各方都難以接受的。網絡
HBase做爲一種KV數據庫,數據訪問模式以主鍵爲核心,當面對非主鍵查詢時,其原生解決方案Filter沒法知足大多數聯機應用的性能需求。因此,不少基於HBase的二級索引方案都在嘗試應對複雜查詢場景的需求。架構
Pharos是基於HBase的技術中間件,研究起點一樣是二級索引,致力於提高多條件複雜查詢的性能,應用在海量數據低延時複雜查詢場景。併發
在啓動研發工做前,咱們對現存的二級索引方案進行了分析,除原生Filter外大體能夠分爲三種。app
這個方案流行度最高,在ES中存儲索引信息,HBase存儲數據自己,二者協同完成索引查詢。方案的優勢是組合成熟產品,實施難度低;但缺點也有不少,首先是總體架構複雜、設備投入增長、運維成本高;其次是性能相對較低,每一次索引查詢,都要先訪問ES得到匹配的索引後,再訪問HBase讀取數據內容,查詢鏈路延長,帶來更多的網絡開銷;最後是開發技能要求較高,程序員必須熟悉ES和HBase兩種產品接口。
Phoenix無疑是一款優秀的開源產品,產品的理念是Put the SQL back in NoSQL。產品成熟,Apache社區背書,都是該方案的優點。
但由於目標高遠,Phoenix的體量也偏重,這樣在沒有商業廠商支持下,運維難度很高(2019年Cloudera宣佈支持Phoenix後,可能會有所改善)。第二點,對SQL的支持成爲它的核心目標,但在不少查詢場景中,SQL並不是不可替代,高性能纔是首要目標,性能倒是Phoenix尚待改進的地方。Phoenix在總體機制上,並無實現完善的索引下推,不少狀況下索引查詢須要從客戶端發起兩次與服務端的交互,第一次得到匹配的索引信息,第二次纔是匹配的數據,這無疑帶來了性能損耗。
在雲計算時代,HBase已經成爲雲服務的標配,部分公有云也提供了二級索引功能。這個方案的優勢固然是廠商的一站式服務,運維成本極低。缺點首先是部分企業由於安全因素沒法使用公有云,例如金融行業;其次在於技術方案自己,例如阿里的HBase二級索引,其內核依然是Elastic與HBase的組合,雖然接口上進行封裝下降了開發難度,但架構帶來的性能損耗依舊存在。
經過上述的分析,咱們發現這些方案都不能知足光大銀行的應用場景,所以咱們決定自研產品。
咱們將產品命名爲Pharos,源自英文單詞 [Pharos],其含義是燈塔。這個名稱有兩層含義:
第一層是詞義自己,燈塔對夜行的船隻進行指引保證其安全地出入港口。而索引指向符合條件的數據地址,用於提高每次查數據訪問操做的效率,二者有神似之處;
第二層含義,Pharos最初是指代亞歷山大燈塔,這也是世界上第一座燈塔。而Pharos是光大銀行首次嘗試自研基礎產品,咱們但願這個命名可以激勵團隊,作出有開創意義的產品。
在Pharos設計目標中最重要的有三點:
低延時:咱們但願將來Pharos的應用場景不只限於數據查詢分析,也可以嵌入到業務交易系統中,這樣低延時就是一個剛性需求;
架構簡單:這樣開發人員能夠很容易上手使用,而運維的成本也很低;
非侵入性:是指對HBase的侵入,事實上除了前述分析的二級索引方案外,還有一些小衆的二級索引方案是直接對HBase進行改造,但這種侵入式改造帶來了後續的版本維護問題,考慮到多數企業不可能維護獨立的HBase版本分支,咱們的方案直接排除了這種技術路線,必須是對HBase非侵入的。
Pharos的研發是從2018年開始的,相對於目前的產品成熟度來講研發過程顯得有點長,主要緣由是開發人力投入相對較小。咱們但願隨着產品的應用推廣,能擴充人員,加快產品的演進速度。
研發過程,咱們受到了不少同類產品的啓發,包括Phoenix、華爲與360等公司的二級索引方案,也借鑑了不少好的設計方法,這裏要特別緻敬一下。
前面講了Pharos的外部特性,接下來我會着重講一些關鍵設計時的tradeoff,但願對你們的研發工做有所幫助。
HBase是沒有索引概念的,咱們首先要解決的是如何存儲索引。
Pharos採用的方式是在數據表增長一個「獨立列族」用於存儲索引信息,利用列族對應獨立文件的特色,造成獨立的索引文件,不會直接受到原始數據量的影響,下降磁盤I/O開銷。這個設計另外一個好處在於,索引與數據同分布,沒必要干預HBase的Region分佈策略。後續的全部設計都是在同Region基礎上,這大大簡化了實現的複雜度。
這種索引與數據同分布的模式,能夠簡稱爲「分區索引」;而索引與數據各自存儲的方式,則成爲「全局索引」。「全局索引」的缺點在於沒法完成索引查詢的下推,優勢是能夠進行全局控制,例如惟一索引。選擇「分區索引」是由於咱們指望實現低延時目標,固然同時也就放棄了對「惟一索引」的支持,至少目前是不支持的。
索引記錄的Key部分,最開始是Region頭信息,保證與數據的同分布,然後是被索引字段的信息,接下來是存儲索引名稱等信息,數據記錄的Key則被拼接爲尾部信息;value部分則存儲反序列化的元數據。
能夠看到,這樣設計的優勢是索引檢索速度快,存儲成本也比較小。因此,當查詢條件較複雜須要創建多個索引時,總體存儲成本依然是可接受的。
傳統的後臺分頁方法是由應用服務記錄每頁的末尾記錄主鍵,這個主鍵一般是由數據庫提供的row number,數據庫自己並不感知分頁動做。對於分佈式存儲的HBase,每一個Region均可能存在分頁斷點,若是延續該思路,應用端要記錄大量斷點信息,不只增長傳輸數據量,也增大了開發的難度。在Pharos的設計中,咱們經過Client做爲匯聚點,緩存每一個Region的斷點信息,在Pharos的Client中增長Session概念,應用端僅需持有Session ID便可順利完成翻頁操做。
根據Pharos的存儲設計,咱們能夠知道索引實質上是與數據行前綴相同的另外一行記錄,保證索引與數據的一致性要使用跨行事務,但HBase自己不支持跨表、跨行事務,這就成爲一個死結,也是幾乎全部二級索引方案都不支持索引事務一致性的緣由。
這個問題的解決比較複雜,因此咱們先簡單介紹下HBase內部機制。HBase採用LSM-Tree模型,在聯機寫入時,數據在日誌和內存中各保留一份,二者經過MVCC與日誌的協調機制能夠保證事務一致性。我畫了一張圖來表示HBase 1.2.6的事務控制邏輯,具體以下:
HBase內部會監控WAL的異常,但在Coprocessor事件體系中並未開「回滾標誌位」,第三方開發者也就沒法回滾相關數據行。
按說,到這裏問題已經無解了,不過某天剛好受到了Percolator事務模型的啓發,找到了另外一種解決問題的思路。既然沒法在寫入過程經過回滾控制異常狀況,那咱們能夠延後在讀取過程當中來補充對異常的操做,也就是說在下一次查詢操做中再次確認並維護索引的一致性。
具體處理過程是,在首次寫入索引信息時,置事務標誌位爲「不肯定」,數據行更新完成後,將該標誌改成「成功」;若是出現回滾,則標誌位保留「不肯定」狀態。查詢操做中一旦發現「不肯定」標誌,則根據索引查找相應的數據行是否存在,如存在,則將該標誌更新爲「成功」。
咱們用流程圖來體現處理過程,以下圖:
該方式付出的代價是寫入時須要兩次更新事務標誌,相對於僅寫入數據行(無索引)確定增長了一些開銷,在測試環境下咱們發現損耗在15%左右,主要是指延時;在查詢環節雖然存在確認索引事務的可能性,但由於其發生的機率極低,不會對查詢產生實質性影響。
目前Pharos主要仍是在內部使用場景中測試,收集需求和問題,近期咱們會發布V0.3版本。新版本會推出一些讓人激動的特性,主要還是圍繞查詢性能的提高,推出Pharos自有的數據組織形式,提供更加豐富的查詢加速手段,完成從二級索引組件到一個完整的技術中間件的演進。
其中,特別重要的一點是完全解決了Region分裂問題,我要火燒眉毛地作個劇透。
Region分裂是HBase數據再平衡的手段,保證每一個數據節點上的數據量分佈大體平均,也會有一些打散熱點的效果。可是,分裂機制卻破壞了索引與數據的同分布,在同類方案中一般採用很重的更新操做來調整索引的位置,追隨數據的分佈狀況。
這種方式顯得過於笨拙,而且更新過程會影響總體方案的可用性。所以,Pharos在V0.22版本中是建議索引延後加載,這樣在數據更新致使的重分佈完成後再更新索引。
實際操做中,這種方式要重複讀取數據文件,延長了總體數據加載週期,對運維操做來講不夠友好。在V0.3中,咱們加入了Pharos自有的數據組織方式,實如今Region分裂時維持索引的同分布效果。
考慮到篇幅的限制,就介紹到這裏。幾個月後,我會擇機與你們分享在新版本的改進,使用了更多首創性的方法,敬請期待。
優秀自研項目徵集:dbaplus社羣【自研出圈】專欄歡迎廣大技術人員和技術團隊投稿參與,分享自研成果和經驗。優先收錄開源或內部自用工具、平臺、系統。
參與方式:發送文章至 editor@dbaplus.cn,詳情諮詢可加微信 Sunny9095
本文分享自微信公衆號 - HBase工做筆記(HBase-Notes)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。