騰訊:互聯網金融行業HBase實踐與創新

徐春明——騰訊金融與支付數據庫平臺組負責人,在數據庫行業有超過10年的工作經驗,擅長MySQL數據庫運維、內核開發。近期深入研究HBase相關技術,負責HBase技術在騰訊支付場景的落地。 

摘要:

本次分享講述的是關係型數據庫在騰訊金融支付場景下遇到的挑戰,選擇HBase背後的主要原因以及我們是如何打造高性能、高可靠、高可用的HBase數據中心。最後是關於HBase在互聯網金融業務方面遇到的挑戰和解決之道。

分享大綱:

1、關係數據庫挑戰—擴展性、可維護性、易用性

2、如何打造HBase中心—高性能、可靠、高可用

3、HBase挑戰和應對—業務侷限、二級索引、集羣複製

正文:

一.關係數據庫挑戰—擴展性、可維護性、易用性

財付通是騰訊在2005年成立的, 2013年逐漸淡出用戶視野,之前負責解決在PC端的支付業務。現階段財付通主要是爲微信紅包提供中後端業務以及服務金融業務。2005年,騰訊的數據庫還比較單一,基本上都是MySQL,每秒的峯值交易量只有幾百,當時我們着重解決數據安全、可容性以及跨城容災等問題。但2015年因微信紅包的出現,交易量峯值一年之內漲了100倍,我們遇到了性能、容災以及可用性等方面的諸多問題,團隊爲解決這些問題做了非常多的工作,最終建立了一個交易系統+歷史數據的基本系統架構。

 以上這個架構主要運用了MySQL的一些組件,包括三種引擎,左邊是實時庫集羣,這個集羣使用的是InnoDB引擎,集羣中的設備性能很好,IO能力強,內存大,CPU也很好,裏面有幾百套的分組,因爲微信支付的交易很複雜,涉及到分佈式事務、同城容災、跨城容災等等很多方面。當時我們使用的是MySQL和InnoDB數據庫,使用過程中發現只要出現一個節日,我們線上的容量就會不夠,因爲高性能的服務器容量是有限的。

而且節日的出現導致交易峯值很高,所以我們出現了鋸齒形的峯值圖。除此之外,數據庫容量也在飛快的增長,基於這些問題我們的解決辦法是進行刪除不重要字段、優化索引、減少數據內容等操作,將歷史數據遷移到歷史庫集羣中,2015年之前我們還不是實時遷移,一般是第二天低峯期批量導出導入然後再刪除。

這樣的方式雖然能解決我們線上交易的高併發海量數據問題,但是在遇到需要歷史數據的情況時依舊會出現很多問題。

我們遇到的挑戰主要是上圖的幾個方面,第一個水平擴展,因爲國家要求金融機構保存交易數據,隨着交易數據與日俱增,單機性能存儲很容易達到瓶頸,架構難以適應目前數據存儲規模,需要考慮數據拆分,但傳統DB拆分困難,工作量很大週期又長。

第二個是數據遷移,我們設置數據遷移策略,定期從交易DB裏將數據寫入到歷史DB中,但其中分庫分表的遷移策略很複雜,造成了上一層Spider的配置非常複雜,容易出錯,所以在業務使用的時候就出現了好幾次查不出數據,導致業務數據不完整。

再一個問題歷史DB一般是廉價的設備,容量很大也很容易出故障,雖然我們有多個歷史庫備機,直接通過複製同步數據來解決系統問題,但數據量實在太大,運行過程中發現備機總是追不上主機,一旦主機出現故障,備機由於延遲不能對外作爲主機使用,只能去修復故障的主機,存在比較大的風險。

在批量查詢上,傳統歷史DB採用TokuDB引擎,數據高度壓縮,磁盤IO、內存性能比較差,大批量的數據掃面對單機性能影響很大,容易拖垮歷史庫。業務查詢方面也出現了查詢數據不準、數據錯亂等等問題。

總的來說,業務開始運行之後,數據庫總是出現問題,導致了很多數據庫口碑的負面影響。

我們當時解決方案就是對比數據庫來選擇性能更好的數據庫,我們對比了Redis、MongoDB還有 HBase,但最終選擇了HBase,主要是看中了它寫高讀低的特點,這個對我們其實影響不大,我們對歷史數據的查詢比較少,也沒有像對在線交易業務的要求那麼高。第二是它的擴展性靈活,只要HBase的集羣穩定,它的擴容就非常容易,HBase的安全性也高,這樣團隊需要做的事情就少了很多,我們可以有更多的精力放在其他方面的工作。

二、如何打造HBase中心—高性能、可靠、高可用

選擇HBase數據中心之後,接下來就是如何打造的問題,當時團隊確定了100萬+每秒輸入,可用率99.9%、0條記錄丟失、錯誤的目標,具體實施步驟分兩步走:

首先要將數據錄入到HBase中,我們的數據源是MySQL,數據經過日誌解析系統DBSync之後緩存再寫入HBase。中間過程本來沒有這麼複雜,當時是負責數據挖掘的leader找到我,因爲他們每次數據統計不準確,接到的投訴比較多。正好我們從成本角度考慮,不用申請這部分服務器,可以快速將數據寫入到自己的HBase。數據錄入後該如何查詢呢?我們交易業務基本用c++實現,HBase用的是Java語言,HBase的thrift可用於跨語言的數據傳輸,所以我們就基於thrift做了一個API來解決跨語言問題。

對於業務流程該如何使用呢?我們不僅僅把HBase當做存歷史數據的平臺,業務流程除開賬務DB外,還有其他交易相關的DB,它們都有同一個問題,容量很容易爆滿,爲了將HBase發揮更大的用處,在特定的場景下,比如一個月前的歷史退款,線上數據不可能保存這麼久,如果時間有一個月以上的退款,我們從HBase查退款,將其寫入MySQL,核心的退款流程和金融流程直接在MySQL做,這樣一來對業務的改動最小,方便業務操作。

HBase的寫入原理是基於LSM思想,先把數據寫入內存之後返回,通過異步方式再落盤,但是這樣在磁盤就有很多小文件,查詢的性能就會非常差。所以,還需要將磁盤上的小文件compaction,減少文件個數。考慮之前積壓的很多compaction任務,我們把small compact線程條加大。再一個是調整WAL日誌的參數,做過關係型數據庫的人可能清楚,HBase裏有四種方式,第一種是直接寫內存不寫硬盤,第二種是異步的落盤,第三種就是寫入操作系統不落盤,第四種是實時寫盤。結合性能與數據可靠性,我們採用寫入操作系統不落盤的方式,考慮有三個副本同時出現三連級故障的可能性比較低,降低IO壓力和時延。再有就是減小regionserver堆棧內存大小,因爲我們業務寫入量實在太頻繁,而cache查詢命中率真非常低,大概只有10%到15%,所以我們將內存全部分給寫入,來提高寫入的量。因爲是批量寫入型業務,我們可以根據需求調整客戶端批量寫入記錄數來提高寫的性能。

優化之後,壓測時達到了每秒150萬+次寫入,達到了很不錯的效果。

之後是讀的優化,我們用的服務器硬件很差,運作率很低,所有的查詢基本全靠磁盤的IO硬能力去抗。LSM思想有個缺點,就是文件數太多影響查詢性能,假如要查詢rowkey=100的數據,文件數有100個,由於每個文件裏可能都有rowkey=100的記錄,那麼我們就要掃描100個文件,耗費時間很長。我們的解決方法是減少在region下的文件數,定期合併文件,把小文件整合成大文件。第二個就是重點隔離,我們把一些表單獨隔離,做一個組,去減小耦合,而且組內機器只允許制定表讀寫請求,避免不同表之間的相互影響。還有參數優化,我們一開始建了很多region表,這樣對整個集羣壓力太大,所以就減少小表,控制其數量。再有一個就是業務按照優先級分等級,不同的級別的業務不同處理,有些索引表可以按年建,有些表可以按月建。最後是硬件升級,重點組配置更高性能的服務器。

優化之後,查詢時耗從開始的260毫秒下降到60毫秒,查詢時耗曲線也逐漸平緩。

在高可用方面,第一個HBase本身必須保證可用,這是最基礎的點,避免Full GC,避免Region Server單個Region阻塞不可用。第二當機器出現故障,怎麼做纔不會影響整個集羣的讀寫?我們使用快速剔除機制,避免單臺服務器負載高影響集羣,第三考慮網絡不可用、機房故障情況,爲此建立主、備集羣,一個集羣裏有三個副本,那麼就共有六個副本,成本很高,我們考慮隔三個月時間就減少到兩個副本,以此來節約成本。第四避免雪崩,無論是Thrift Server還是RPC的調用,操作時間都是比較長的, 這就需要縮短Thrift Server超時時間,減少重試次數。最後按業務重要級別分組,減少和其他機器的耦合。

上圖是高可用單點保障的流程圖:從客戶端寫入一個數據,查閱Meta表獲取RS位置,把數據寫到RegionServer中,然後異步寫到Hadoop層去同步數據。可以看到在集羣內只有Region Server是單點,其它組件都有高可用方案。當Region Server故障時,集羣內遷移恢復一般需要幾分鐘,對於OLTP業務來說是不可接受的。可選擇的方案是業務快速遷移到備集羣,或者使用region replica。

我們通過三種方法來保證數據的準確性,第一種是數據對賬,在金融系統中都會有數據對賬,我相信無論什麼系統都會有bug,對賬十分關鍵不能出錯,我們有10分鐘增量對賬,有冗餘數據對賬,要求數據寫入來源IP與覈對IP分開,來源DB於對賬DB分開。第二個從流程規範來降低人爲失誤,通過一些系統化的方法來運維。第三個是提高監控效率,加了秒級監控,如果出現問題能快速發現馬上解決,出現對賬異常立刻上報神盾安全系統。這樣通過上面的三種方法,我們把數據的準確性提高了一個量級。

這裏單獨講下update的特殊處理,金融業務對數據的處理分兩種,第一種是直接映射的,像用戶資金流失這種比較簡單。比較困難的是第二種時間批量對賬,比如像一些餘額和某些訂單的狀態,我們一天的數據量有幾百億,該如何應對平均一秒幾十萬的對賬呢,爲此係統加了修改時間,使得對賬更加準確,但同時會造成數據的冗餘,比如一個單號對應我們交易系統裏的一條記錄,但在HBase中沒有update,全部是映射,這樣就會有兩條記錄,這樣狀態下退款是不能成功的,爲解決這個問題,我們將MySQL binlog中update拆分成delete + insert兩條消息,使得HBase中保留一條記錄。

但這樣還有一個問題,有可能在同一秒鐘有兩次記錄,就是說同一個單號在一秒鐘內完成交易,拆分數據時,有可能導致兩條數據記錄都刪掉,如果沒有一定的併發量,這個問題是不會出現的。我們在處理這個問題時採取在拆分時加個序號,並且保證insert在delete的後面,這樣就能確保留下一條記錄。

我們在實際運用HBase過程中,也遇到了很多其他問題。第一個是遇到HBase讀寫線程隊列分開,因爲我們寫入量遠遠多於讀的量,比如退款業務只有寫沒有讀,我們調整了hbase.ipc.server.callqueue.read.share=0.3的參數,來保證一定的讀寫線程。還遇到某一臺DataNode負載高導致整個集羣寫入量下降非常明顯,我們增加了秒級監控可以快速發現,快速遷移region解決。

之後還有可維護性方面的問題,HBase有些配置不能動態修改配置、不支持命令查看HBase集羣運營情況、缺少彙總統計功能。還有就是容量均衡,我們的數據量在不斷增加,我們有幾十臺服務器磁盤容量已經用了99%,有的服務器容量使用還不到1%。所以需要在服務器間遷移數據。可以不在HBase層操作,而是從hdfs層停datanode節點,讓namenode遷移。

總的來說,雖然HBase有一些缺點,但HBase的優勢更加明顯,它性能穩定有利於更好地解放人力,節約成本。

三、HBase挑戰和應對—業務侷限、二級索引、集羣複製

下面是我對於HBase的想法, 現階段HBase的應用場景只有兩種,有比較大的侷限性,因爲它不支持SQL,不支持跨行跨表事務,不支持二級索引,而且讀時延大。它不能用在OLTP(On-Line Transaction Processing聯機事務處理過程)業務,比如支付業務的核心流程,但適合存放歷史數據,處理歷史數據的對賬、歷史數據的回溯等需求。

 那如何來解決事務問題呢?第一個,HBase雖然不支持跨行跨表事務,但可以多表變單表,實施單表設計與HBase單行事務。所以在處理數據表的事務時,儘量多表換單表,避免分佈式事務。

 第二個事務是業務分佈式事務,如果做金融業務,在HBase中改動難度太大,可以在業務層進行改動,採用兩階段提交協議,分成P,C,F階段。事務管理器控制事務的提交或者回滾。資源管理器對應表,一張表拆分多個資源管理器,採用有鎖方案。事務管理器無狀態,高可用方案比較成熟。資源管理器有狀態,可以是M-S方案,但也可以設計成M-M方案,無論是分佈式還是單機,把HBase進行重組,利用HBase的單行事務功能來控制併發。

下面是具體的例子

 第三個是開源分佈式事務框架。主要是兩種OMID和Percolator,共同點是兩階段分佈式。不同點是OMID有個全局事務,通過它來控制併發,控制哪個事務該回滾。Percolator主要是運用Hbase協處理器的技術,實踐起來比較困難。

上圖是協處理器的應用,第一個是Phoenix,它支持sql、二級索引,通過Coprocessor實現,但它不穩定,數據量大的情況容易造成HBase崩潰。第二個Coprocessor實現,使用Observer實現在寫主表前先寫索引表,最後是時間庫表,表設計成按月或者按日分表,新建索引時不用copy歷史數據。

HBase有複製的功能,但在使用過程中發現它不穩定,我們後來通過應用來實現雙寫功能。

 

上圖是HBase和Hadoop支持的隔離方案,雖然能在一定程度上做到了隔離,但這種隔離不徹底,耦合比較強,定位問題比較複雜,依舊不能實現業務上隔離。

最後,談一下數據庫的目標和方向。無論是傳統的關係型數據庫還是分佈式數據庫,努力的方向就是提供高可用、高性能、高併發、好用、易擴展的數據服務。目前市面上的數據庫非常多,但所有的數據庫或多或少總有幾個特性實現得差強人意,所以也沒有出現“一統江湖”的數據庫,導致數據庫應用出現百花齊放的局面,這也是各個數據庫團隊努力的方向和動力。

文章來源:http://blog.itpub.net/31547542/viewspace-2213514/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章