轉自:http://www.aboutyun.com/thread-7297-1-1.htmlhtml
Facebook放棄Cassandra以後,對HBase 0.89版本進行了大量穩定性優化,使它真正成爲一個工業級可靠的結構化數據存儲檢索系統。Facebook的Puma、Titan、ODS時間序列監控系統都使用HBase做爲後端數據存儲系統。在國內公司的一些項目中也用到了HBase。
HBase隸屬於Hadoop生態系統,從設計之初就十分注重系統的擴展性,對集羣的動態擴展、負載均衡、容錯、數據恢復等都有充分考慮。相比於傳統關係型數據庫,HBase更適用於數據量大、讀寫吞吐量很是高、對數據可靠性一致性及數據操做的事務性要求較低的應用。
HBase使用HDFS做爲存儲層,HDFS屏蔽了底層文件系統的異構性,集羣數據的負載均衡、容錯、故障恢復都對上層透明。這使得HBase的結構極爲簡單清晰,集羣擴展性很是突出。同時HBase使用ZooKeeper做爲分佈式消息中間件,管理集羣運行時各節點狀態,保證分佈式事務的一致性。
經過使用HDFS和ZooKeeper,HBase要達到管理節點Master和服務節點Region Server運行時無狀態的設計理念,服務節點Region Server中管理的MemStore和BlockCache等結構的本質意義都是緩存。系統運行時隨時替換、添加或刪除服務節點時不須要依賴以前服務節點保存的任何信息,負載均衡、集羣擴展及失效時數據恢復的處理流程都極爲簡單,添加服務器或發現服務器下線以後對集羣負載從新均衡等操做在不須要回滾日誌的狀況下都能在1分鐘甚至幾秒鐘完成。HBase中的管理節點HMaster的工做則只是維護ZooKeeper中存儲的集羣狀態變化的時序,充當WatchDog的角色。當管理節點出現異常狀況時,Backup Master能夠當即激活,不影響集羣的正常使用。
HBase有哪些問題?前端
HBase也有衆多用戶詬病的不足,例如原生HBase不支持索引(衆多NoSQL數據都把索引做爲本身支持的基本功能,例如也有衆多用戶的MongoDB)查詢方式單一,只支持基於主鍵的數據讀寫和範圍查詢,對非主鍵列的數據篩選只能經過過濾器低效完成,若是用戶從客戶端創建索引,則須要本身維護索引表與數據表的一致性,同時HBase也不支持跨行或跨表事務,操做衝突致使失敗時數據回滾這些複雜邏輯都須要用戶本身完成。
HBase底層使用HDFS做爲持久化層,因爲HDFS保持副本一致性的方式很是簡單,一旦文件生成便不支持數據的修改。HBase不得不使用LSMTree結構經過刷寫新文件並經過同時查詢多個存儲文件中的內容,而後按時間戳歸併結果來模擬實時修改數據。因此在經歷長時間數據寫入以後會生成許多存儲文件,傳統機械硬盤每秒隨機尋道次數很是有限,且隨機尋道時間都在10ms左右,遠大於HBase查找block等其餘讀取數據時必要操做的時間,從多個存儲文件中查找數據會引起讀取性能尤爲是隨機讀取性能成倍降低。
在生成多個存儲文件以後,HBase爲了緩解數據讀取性能的降低須要按期進行數據文件歸併操做Compaction。因爲Compaction通常狀況下須要讀取一個分區的全部存儲文件,並將記錄排序後從新寫到一個新的存儲文件中。執行期間會消耗大量系統網絡帶寬、內存、磁盤I/O以及CPU資源,很是容易形成系統過載。一旦帶寬開銷過大形成網絡時延或者內存開銷過大引起Region Server執行長時間的GC操做時,有可能致使其長時間對外中止服務。若是中止服務的時間維持到ZooKeeper租約超時,Master會認爲此服務器宕機並通知其下線,而後從新將此Region Server上承擔的數據分發到其餘服務器上。這個過程一般會持續2~3分鐘,而最壞狀況下若是同時這臺Region Server上正好有Meta表,就可能致使整個集羣在此期間沒法對外提供服務。
此外,因爲HBase底層使用列存儲結構固化數據,處理非稀疏數據時會有較大的數據冗餘形成數據膨脹。一般狀況下,存入10列左右的數據,不計副本的膨脹率爲3~5倍。想減小這種數據膨脹最爲簡單的辦法是儘可能減小行鍵、列簇、列的長度。最極端的狀況下,咱們曾經把數據都寫在HBase表的RowKey中,以此減小膨脹率提升數據範圍查詢和隨機讀取的速度。這種方式將HBase退化爲KeyValue存儲來提高讀寫性能,但大多數應用仍是但願數據存儲結構儘可能貼近應用的邏輯結構或儘可能貼近關係表中表的結構,因此不得不使用Snappy等壓縮算法對數據進行壓縮或是採用HFile V2使用行前綴壓縮來減小冗餘。但這兩種壓方式特別是採用壓縮算法後都會大幅度影響HBase隨機讀取的性能。壓縮算法爲了提升壓縮效率一般須要維護一段合適的buffer,壓縮時對buffer內的數據統一壓縮成一個壓縮塊。HBase中存儲文件的block默認大小爲64KB,而Snappy壓縮buffer爲256KB,這會大大增長一次隨機讀取所須要處理的數據量,HBase本就不優秀的讀取性能會進一步受到影響。
推薦系統介紹與特色算法
搜狐推薦引擎系統是從零基礎的狀態下逐步成型的,通過很是緊張的開發。目前已接入幾億用戶的行爲日誌,每日資訊量在百萬級,每秒約有幾萬條左右的用戶日誌被實時處理入庫。在這種數據量上要求推薦請求和相關新聞請求每秒支持的訪問次數在萬次以上,推薦請求的響應時延控制在70ms之內。同時系統要求10秒左右完成從日誌到用戶模型的修正過程。
10秒左右的實時反饋成爲目前系統的主要難點,爲此咱們須要維護幾億用戶200GB的短時間屬性信息,同時依靠這些隨用戶行爲實時變化的屬性信息來更新用戶感興趣的文章主題,同時實時計算用戶所屬的興趣小組,完成由短時間興趣主導的內容推薦和用戶組協同推薦。
用戶短時間興趣屬性須要根據用戶每次的點擊瀏覽和下拉刷新三種操做頻繁更新和修改。一旦系統收到用戶的日誌須要查找出對應相關資訊的全部信息,同時還要找到用戶相關的屬性數據,根據操做屬性,對全部相關屬性進行加權或減權。加權操做大體包括點擊、瀏覽時長、劃屏;減權操做則主要是推薦曝光。這些數據都要實時回寫到用戶庫中,同時每次推薦也會直接從庫中獲取用戶短時間興趣模型,以此捕捉到用戶當前的瀏覽閱讀興趣。除此以外,還有一些頻率較低的操做,例如記錄用戶瀏覽歷史、週期性計算熱門文章。這些操做都是在HBase上完成的。
系統中最爲苛刻的需求是處理每秒幾萬條左右的用戶日誌,單條日誌對應的資訊屬性約爲5到10個,同時更新屬性最簡單的狀況須要讀出用戶原有對應屬性而後進行加權或減權後存回屬性表。所以,存儲系統處理日誌時對應每秒隨機讀寫次數約爲幾十萬次。系統還須要處理每秒萬次的推薦請求,這麼多推薦請求都須要讀取每一個用戶當前最新的短時間模型,同時請求的返回時間須要控制在70ms之內,這樣包括磁盤隨機尋道甚至數據命中磁盤、JVM GC都成爲存儲系統須要盡力避免的問題。
知足苛刻的隨機數據讀寫需求數據庫
目前整個系統承擔壓力的核心部分就是HBase,HBase讀寫最爲頻繁的數據是用戶短時間屬性。而原生HBase最大的問題之一就是數據隨機讀寫速度太慢。爲了知足目前應用的需求,咱們基於HBase開發了一套徹底利用內存的數據存儲系統。下面將分兩部分介紹基於內存的存儲系統和HBase如何承載前端巨大的數據增刪改查的壓力。
MemT承擔系統核心壓力後端
因爲咱們代碼裏將HBase上的內存數據存儲系統的包名叫memtable,因此這裏把這套東西簡稱爲MemT。MemT目前單集羣部署了10臺服務器(10對10熱備)主要存儲200GB用戶短時間興趣和最近30天文章的摘要信息。
MemT主要功能包括單服務器每秒支持近20萬次增刪改查操做,支持與HBase相同的行、列簇、列的表結構,支持TTL時間戳數據管理,支持HBase中全部Filter的數據過濾。同時還封裝了一些系統經常使用函數,例如求一行數據中列或列值TopN、按時間平滑數據和計算衰減等。
爲了保證系統的可用性,MemT在單個集羣中會維護兩張內存表互爲備份,節點宕機時客戶端會自動切換到當前可用的副本上,應用通常對宕機無感。同時MemT還利用了HBase自身的負載均衡(balancer)及宕機Region恢復策略來管理本身的內存數據分片。在單個副本不可用時,客戶端會快速切換到可用副本上,因此不會出現HBase RS宕機時等待session超期的狀況。宕機後中止服務的節點上全部數據會被分配到集羣其餘服務器上,收到新數據分片的服務器開始加載數據到內存中同時對外提供服務。集羣內存中的各個備份之間經過HBase中一張日誌表同步數據,客戶端能夠選擇把數據寫到日誌表中,也能夠強制刷寫MemT各服務端的內存來同步數據。日誌表被Hash爲40個Region分佈在集羣中,某個服務器宕機以後,其數據也會被均分到集羣的其餘服務器上,由整個集羣來恢復宕機服務器內存中的數據,因此數據恢復的速度很是快,恢復完近期日誌中的數據後還須要恢復dump表中的內容。這個過程後面詳細介紹。目前線上集羣掛掉一臺Server,從日誌檢查到恢復內存約20GB數據的時間不到1分鐘。
當內存中數據增加超過用戶配置的閾值時(目前是25GB),系統會按Region大小排序後,從最大的Region開始按LRU規則把內存中的數據淘汰到對應HBase的dump表中,同時在內存裏將該行dump標記置爲true。當系統再次讀取該行時,dump表裏對應的內容會再次被加載到內存中按時間戳歸併結果,同時修改dump標記爲false。若是dump標誌位爲true,系統更新此行內的數據也會被直接放到dump表中來節約內存。dump表對應的HBase Region和MemT對應的數據分片會被分配到同一臺服務器上,來保證其交互時的性能。
系統日誌表裏的內容標記爲6個小時過時,同時每4個小時系統會將內存中的數據作一份快照。快照流程與內存不足時將數據存放到dump表中的流程類似。不一樣的是快照不影響每行數據的dump標誌位,當內存分片完成快照以後,恢復數據時快照以前的日誌就能夠丟棄並直接從快照中恢復數據。
另外,系統要求每次推薦請求相應時延在70ms。爲了讓MemT在每秒上萬次請求時不產生大量內存碎片而頻繁GC,咱們從新改寫了HBase的RPC層,爲其中Connection、Handler這些處理RPC並主要申請內存的類設計了緩存,當RPC請求及返回數據大小在必定時間內波動範圍保持不變時,Connection和Handler幾乎能夠重用所有處理完廢棄的數據結構,以此來消除內存垃圾的產生。咱們曾經一度廢棄RPC Reader這一角色,全部請求都由Handler接收處理並直接返回。這樣內存佔用處理的通量都會有所優化。不過缺乏請求隊列以後請求的先後關係沒法保證,沒法保證先到先服務,客戶端會隨機出現服務時延異常高的請求。
HBase使用有哪些原則?以下:
緩存
1. 規避事務類應用。
HBase默認只保證多用戶單行數據操做的數據時序和一致性。若是用戶須要跨行甚至跨表事務支持則須要在客戶端同時擁有多行數據的鎖。當HBase支持高併發數據訪問時,很可能因爲客戶端各類問題形成死鎖同時影響數據訪問。若是用戶須要對錶段甚至表進行加鎖則須要經過Coprocessor或改動Region Server代碼在服務端處理加鎖請求。這樣的操做十分危險,可能致使整個集羣全部RS的Handler線程因爲循環等待而耗盡,進而使全集羣對外中止服務。
目前基於HBase處理事務代價最小的方式是,數據版本經過不一樣操做申請不一樣的事務ID,同時讀取數據時過濾未完成事務的數據版原本實現。總之,基於HBase處理事務類或強數據一致類的應用有些南轅北轍,違背HBase高擴展大併發高通量數據存取的設計理念。
若是應用對事務要求較高,那麼能夠選用傳統關係數據庫或新興的一系列NewSQL數據庫。例如,內存數據庫VoltDB,其使用處理線程與CPU及數據分片綁定的方式,全部數據修改操做先發送到多個副本中的主副本上,由主副本管理線程統一肯定順序再由各個副本分別執行操做。使一般須要屢次加鎖解鎖的事務操做能夠在徹底無鎖的狀態下完成。同時實測的每秒事務處理量也遠超通常關係型數據庫,是OLTP類應用不錯的選擇。
2. 避免長時間大量數據寫入,同時均衡集羣負載。
因爲HBase須要經過Compaction操做來合併寫入的數據來優化數據讀取性能,而Compaction操做十分消耗系統資源。爲了使系統能穩定提供服務,最好手動控制數據表Compaction的時間,同時減小寫入數據量來減小系統的I/O資源消耗,用戶能夠打開HFile的前綴壓縮而且縮短行、列簇及列的長度,同時合理設計表主鍵將寫入數據分散到全部服務器來緩解壓力。同時中止系統自動,挑選低壓時段,定時滾動觸發。最後用戶最好關閉HBase的split功能,同時在定義數據表時就預先劃分數據分片,這樣一方面能夠避免新表因爲分片數少,初期讀寫通量都較低的狀況,另外一方面能夠避免split帶來的多種問題。最後用戶最好本身實現balance功能,例如按表粒度的balance,這樣能使負載更快地分散到整個集羣中。
3. 保證Meta表可用性。
HBase中全部用戶表的Region都依賴Meta表來肯定其當前位置,Meta表的可用性關係到整個集羣可否正常對外提供服務。爲保證Meta表可用,咱們按期將Meta表移動到集羣負載最輕、內存消耗最小的服務器上。同時移動Meta表會將最新修改刷寫到文件系統,防止Meta出現數據丟失。
4. 減輕ZooKeeper節點壓力。
HBase全部服務節點及數據分片調度操做時序、全部服務節點的生存期Session以及客戶端查詢服務節點地址等操做都是由ZooKeeper完成的。ZooKeeper節點之間也須要全量同步全部數據,所以下降節點負載、保證網絡可達很是重要。一般在服務器資源充足的狀況下,建議將Master、Backup Master和ZooKeeper節點部署在一塊兒。同時不在節點上運行Region Server等資源消耗較多的進程。
5. 避免隨機讀取,利用緩存減小熱數據延時。
目前推薦系統內讀取、更改最頻繁實時要求最高的用戶數據短時間興趣數據被放到了MemT中,但還有一些數據量更大,但更新和修改並無那麼頻繁的數據被存儲在HBase中。例如,全部新聞資訊的原始數據,全部用戶的長期興趣模型等,這些數據基本入庫以後就不會更新,同時前端推薦服務器讀取一遍數據基本就能夠把較熱的部分數據緩存本地並很長時間不須要再次訪問HBase,這些數據加速方式基本就是各應用使用本地Cache。
6. 防止Region Server假死。
一般狀況下,Region Server進程因爲GC或其餘緣由假死或退出時,ZooKeeper中維持的Session會超期,並由此引起Master的數據恢復流程。但極少數狀況下,咱們也遇到Region Server沒法對外提供服務但Session並不超期的狀況,這種狀況會形成一部分數據一直沒法訪問。爲了不這種狀況分生,咱們的系統監控進程會按期讀取每片Region的首行數據,在屢次無返回或者超時的狀況下調用腳本重啓Region Server,快速發現服務節點異常,快速下線從新分配數據。此外,因爲Region Server由於GC發生宕機的狀況很是常見,咱們會定時重啓全部服務,使下線的Region Server從新啓動,同時均衡集羣負載。
前面介紹了不少使用HBase須要注意的問題,其實實際使用中HBase大多數時間仍是很是穩定而且有不錯的性能。HBase上順序Scan和數據寫入速度都能達到上萬次每秒。目前系統中還有不少相似數據倉庫存儲過程的數據整理操做,因爲涉及的數據量比較大也被放到HBase上執行,例如各個源之間數據結構的轉換、日誌數據用戶數據資訊數據的拼接以及文章熱度發佈量的計算等。這些操做大多都是利用HBase順序讀寫,雖然處理的數據量稍大,但也沒有對線上系統形成過分的壓力。將這些操做直接在HBase上執行,簡化了系統總體的複雜程度。
總之,HBase可以利用大量廉價的PC Server提供很是出色的高併發且大流量的數據讀寫性能。即使不作細粒度的優化,簡單增長服務器數量也能成倍提升讀寫通量增長系統的處理能力和穩定性。
系統的其餘模塊服務器
目前系統其餘模塊還包括用做傳遞日誌和其餘消息的Kafka隊列,離線計算用戶模型的Hive、Pig、Mahout,和其餘一些運維管控系統。Kafka消息隊列的讀寫性能很是優秀,但會出現消息亂序以及消息重複發佈的狀況。系統目前全部統計指標數據都是經過Hive處理日誌得出的。Hive的開發難度很低易於使用而且產量很高。Pig主要用於初期日誌清洗,Mahout則用於用戶模型計算等方面。
結束語網絡
內容推薦引擎系統集成了重多開源系統,是站在巨人的肩膀上摘到當前的成果。
對比其餘NoSQL系統(例如Redis、MongoDB、Cassandra等),HBase基於HDFS不支持復瑣事務、最初設計中最大的考量因素就是擴展性,其設計的初衷就是基於集羣、擴展性好、故障恢復機制清晰高效、基於水平分片的負載分發模式易於調整。
這些下降了咱們設計系統的難度,良好的擴展性讓咱們沒必要擔憂因爲系統用戶量倍增加,不得不本身處理數據分片、調度、同步、可靠性等一系列問題。集羣規模隨用戶規模同步線性擴展是最廉價的升組系統的方式。
同時HBase簡單清晰的代碼結構也讓咱們解決其各類問題或定製化二次開發成爲可能。HBase中衆多功能強大的組件,例如Bloom過濾器HFile和RPC等,也被拆解出來從新用於其餘系統的開發。目前系統中的HBase以及基於HBase的一系列衍生系統已能夠勝任大部分苛刻的需求,而且長期在低負荷穩定狀態下對外提供服務。