1. 程式人生 > >HBase多租戶機制分析

HBase多租戶機制分析

了解 同學會 人性 pac 觀察 它的 維度 handle rac

  在HBase1.1.0發布之前,HBase同一集群上的用戶、表都是平等的,沒有優劣之分。這種’大同’社會看起來完美,實際上有很多問題。最棘手的主要有這麽兩個,其一是某些業務較其他業務重要,需要在資源有限的情況下優先保證核心重要業務的正常運行,其二是有些業務在某些場景下會時常’抽風’,QPS常常居高不下,嚴重消耗系統資源,導致其他業務無法正常運轉。
  
  這實際上是典型的多租戶問題,社區針對這個問題提出了相應的應對措施,主要有如下三點:
  
  (1)資源限制,主要針對用戶、namespace以及表的QPS和請求大小進行限制,詳見HBase-11598
  
  (2)資源調度,主要針對任務進行優先級調度,通常會優先調度實時交互而且小的任務,而批量操作任務或者長時間操作任務(大scan)優先級相對較低,詳見HBase-10993
  
  (3)資源隔離,將不同表通過物理隔離的方式分布到不同的RegionServer上,詳見HBase-6721
  
  本文將會重點介紹HBase中的資源限制方案 – Quotas,主要對其使用方式、實現原理進行介紹,並對其實際效果通過實踐進行驗證。另外,本文還會對HBase的資源調度原理進行簡單介紹,並對主要配置進行講解。
  
  資源限制-Quotas
  
  Quotas使用條件
  
  (1)HBase版本在1.1.0以上,或者低版本HBase應用了對應的Patch(HBase-11598)
  
  (2)Quotas功能默認是關閉的,需要在配置文件hbase-site.xml中通過設置hbase.quota.enabled為true打開。設置完成之後,需要重啟HMaster才能生效。
  
  Quotas語句詳解
  
  [java] view plain copy
  
  hbase> set_quota TYPE => THROTTLE, THROTTLE_TYPE => READ, USER => ‘u1‘, TABLE => ‘t2‘, LIMIT => ‘10req/sec‘
  
  (1)Quotas分別支持表級別以及用戶級別資源限制,或者同時支持表級別和用戶級別,如示例所示
  
  (2)THROTTLE_TYPE可以取值READ / WRITE,分別對隨機讀和隨機寫進行限制
  
  (3)LIMIT 可以從兩個維度對資源進行限制,分別為req/time 和 size/time,前者限制單位時間內的請求數,後者限制單位時間內的請求數據量。需要指明的是time的單位可以是sec | min | hour | day,size的單位可以是B(bytes) | K | M | G | T | P,因此LIMIT可以表示為’1000req/min’或者’100G/day’,分別表示’限制1分鐘的請求數在1000次以內’,’限制每天的數據量為100G’
  
  常用Quotas語句
  
  [sql] view plain copy
  
  hbase> set_quota TYPE => THROTTLE, TABLE => ‘t1‘, LIMIT => ‘1000req/sec‘
  
  hbase> set_quota TYPE => THROTTLE, THROTTLE_TYPE => WRITE, USER => ‘u1‘, LIMIT => ‘10M/sec‘
  
  註意事項
  
  (1)set_quota命令執行的限制都是針對單個RegionServer來說的,並不是針對整個集群
  
  (2)set_quota命令默認執行後並不會立刻生效,需要等待一段時間才會生效,等待時間默認為5min。可以通過參數 hbase.quota.refresh.period 進行設置,比如可以通過設置
  
  hbase.quota.refresh.period = 60000將生效時間縮短為1min
  
  (3)可以通過命令list_quotas查看當前所有執行的set_quota命令
  
  Quotas – 實現原理
  
  原理很簡單,如果請求數超過設置的Quota數,就拋出異常!有同學會說也沒在日誌中看到任何異常嘛,這是因為這類異常日誌級別是debug,而默認的日誌輸出級別為info,可以通過調整log4j來查看。但是這類異常實在太多,沒有必要輸出。
  
  Quotas – 實踐效果
  
  了解了Quotas的使用方法以及基本原理,是不是很想試一試它的功效,筆者在測試環境做了如下的測試:
  
  1. 測試硬件情況
  
  集群規模
  
  RS JVM內存配置
  
  硬盤
  
  HBase版本
  
  YCSB版本
  
  4臺RegionServer
  
  72G
  
  12 * 3.6T
  
  1.1.2
  
  0.8.0
  
  2. 測試環境新建兩張表,分別稱為A和B。兩張表的數據構成都相同,10億條數據,每條數據500Bytes,總大小500G左右。
  
  3. 分別使用兩個YCSB客戶端分別對這兩張表執行讀寫混合操作(讀寫比為1:1),再然後對B表不斷執行set_quota操作,對該表QPS進行限制。再分別觀察A表和B表的QPS以及讀延遲變化情況。
  
  4. 為了方便理解,下面測試結果中A表稱為Unthrottle_Table,B表稱為Throttle_www.taohuayuan178.comTable。測試結果如下:
  
  通過測試基本可以看出,隨著B表執行的QPS限制越來越嚴格,上圖中Throttle_Table表對應的吞吐量(紅色柱狀圖)越來越小,相應Unthrottle_Table表(紫色柱狀圖)對應的吞吐量卻越來越大,這是因為B表執行QPS限制之後各種硬件資源就會更多地分配給A表。
  
  總體來說,Quotas功能總體看來基本完成了資源限制的職能,達到了資源限制的目的。同時支持用戶級別和表級別,另外同時支持請求大小和請求數量兩個維度,基本涵蓋了常見的資源限制維度;另外,易用性也是一大亮點,比較人性化,只需要在Shell界面上敲一行命令就可以搞定。
  
  資源調度
  
  在 0.99版本之前,HBase只提供了一種請求隊列類型:FIFO隊列,意為先到的請求會優先被處理,後到的請求需要等待之前的請求被處理完。這樣的設計有一個致命的缺陷,就是在線交互式查詢有可能會被離線大scan長時間阻塞,而從優先級的角度講在線交互式查詢無疑更加重要。
  
  0.99版本之後,HBase將默認請求隊列由FIFO類型改為了Deadline類型,用來解決上述缺陷。提起DeadLine隊列,很多對Linux IO調度算法比較了解的同學並不陌生,Linux IO常用調度算法主要有Noop、CFQ(Completely Fair Queuing)以及Deadline,其中Noop調度算法基本可以認為就是FIFO算法,因此同樣存在上述弊端;而CFQ算法會按照IO請求的地址進行排序,這樣處理的目的在於盡量少地減少磁盤移動,實際效果來看確實極大的提升了IO的吞吐率,但是相比Noop,部分IO請求有可能會一直排到隊尾,存在餓死的情況。Deadline算法首先將讀寫IO隊列進行了分離,而且讀IO優先級要高於寫IO優先級;除此之外,它還會為每一個IO請求設置一個時間戳,用以判斷請求是否長時間沒有得到處理,進而需要優先處理。需要知道的是,對於常見數據庫環境來說(Oracle,MySQL等www.567860.cn ),Deadline算法總是最佳選擇。
  
  那HBase新增的Deadline算法和Linux IO中Deadline算法是否一樣呢?答案是肯定的,至少兩者實現思路基本是一致的。接下來主要結合HBase請求調度源碼對Deadline算法進行深入分析。
  
  Deadline算法基於Deadline類型隊列實現,Deadline類型隊列和FIFO類型隊列不同,屬於優先級隊列,裏面的元素會按照優先級進行排序,優先級高的排在隊首,優先級低的排在隊尾。很顯然,Deadline算法目標是使得在線交互式查詢請求優先級更高,而離線長scan請求優先級更低。除此之外還有一個通常不會被註意的目標:不能出現任何請求被餓死!在弄懂具體的實現機制前,需要首先搞清楚一個問題:如何量化一個scan的請求長短?
  
  如何量化一個scan的請求長短:這個問題的理解需要對scan的流程有一個大體認識,一次scan請求並不會將所有數據查詢返回,這一方面是因為在數據量大的場景下諸如帶寬之類的系統資源會被嚴重消耗,另一方面也有可能會因為數據量大導致客戶端OOM。因此HBase實際上將一次scan請求分為多次連續的next小請求執行,每次查詢紀錄數用戶可以配置,默認為100條。這樣假如一次scan查詢總紀錄數為1000,每次查詢返回100條,就需要10次客戶端到服務器端的next請求。看到這裏,很多童鞋已經明白,可以通過當前RPC請求次數(即next RPC調用次數)粗略地衡量scan的長短,比如當前scanA的RPC請求次數為10,scanB的RPC請求次數為5,就可以認為scanA長於scanB,那理論上scanA的這次請求優先級就會低於scanB的這次請求。
  
  HBase在具體實現中會為每一個請求設置一個deadline(時間期限),代表這個請求的處理期限,deadline越小,請求優先級越高。
  
  這個deadline參數是理解HBase資源調度的關鍵,它由兩部分構成:後半部分的核心在於vtime,代表當前scan的next請求次數,可見vtime越大(scan越長),對應的deadline越大,優先級越低;因為設定get操作的vtime為0,因此同等條件下get操作優先級最高;可見,通過vtime就可以實現請求優先級功能。那對於長scan,會不會出現因為優先級太低長時間得不到處理餓死的情況呢?這就需要看看前半部分,timestamp表示請求點的絕對時間戳,設置絕對時間戳是為了保證該請求的deadline肯定早於5s(等式後面部分最大就是5s)之後所有請求的deadline,從而能夠保證不會被餓死;
  
  好吧,上面不是說Linux IO調度系統中Deadline算法還實現了讀IO和寫IO的分離,那HBase實現了麽?當然,用戶只需要通過簡單的配置就不僅可以實現讀請求和寫請求的分離,還可以實現了scan請求的分離。
  
  默認場景下,HBase只提供一個隊列,所有請求都會進入該隊列進行優先級排序。用戶可以通過設置參數hbase.ipc.server.callqueue.handler.factor www.thy157.com來設置多個隊列,隊列個數等於該參數 * handlercount,比如該參數設置為0.1,總的handlercount胃150,則會產生15個獨立隊列。
  
  獨立隊列產生之後,可以通過參數 hbase.ipc.server.callqueue.read.ratio 來設置讀寫隊列比例,比如設置0.6,則表示會有9個隊列用於接收讀請求,6個用於接收寫請求;另外,可以通過參數 hbase.ipc.www.huarenyl.cn server.callqueue.scan.ratio 設置get和scan的隊列比例,比如設置為0.1,表示1個隊列用於scan請求,另外8個用於get請求;
  
  總結
  
  本文主要介紹了HBase中多租戶實現中的兩個重要手段:資源限制以及資源調度,對其工作原理以及使用方法進行了解析。

HBase多租戶機制分析