HBase查詢優化之Short-Circuit Local Reads

1.概述

在《HBase查詢優化》一文中,介紹了基於HBase層面的讀取優化。因爲HBase的實際數據是以HFile的形式,存儲在HDFS上。那麼,HDFS層面也有它本身的優化點,即:Short-Circuit Local Reads。本篇博客筆者將從HDFS層面來進行優化,從而間接的提高HBase的查詢性能。
html

2.內容

Hadoop系統在設計之初,遵循一個原則,那就是移動計算的代價比移動數據要小。故Hadoop在作計算的時候,一般是在本地節點上的數據中進行計算。即計算和數據本地化。流程以下圖所示:linux

 

在最開始的時候,短迴路本地化讀取和跨節點的讀取的處理方式是同樣的,流程都是先從DataNode讀取數據,而後經過RPC服務把數據傳輸給DFSClient,這樣處理雖然流程比較簡單,可是讀取性能會受到影響,由於跨節點讀取數據,須要通過網絡將一個DataNode的數據傳輸到另一個DataNode節點(通常來講,HDFS有3個副本,因此,本地取不到數據,會到其餘DataNode節點去取數據)。緩存

 2.1 方案一:客戶端直接讀取DataNode文件

短迴路本地化讀取的核心思想是,因爲客戶端和數據在同一個節點上,因此DataNode不須要在數據路徑中。相反,客戶端自己能夠簡單地讀取來自本地磁盤的數據。這種性能優化集成在CDH的Hadoop相關項目中,實現以下圖所示:安全

這種短迴路本地化讀取的思路雖然很好,可是配置問題比較麻煩。系統管理員必須更改DataNode數據目錄的權限,以便客戶端有權限可以打開相關文件。這樣就不得不專門爲那些可以使用短迴路本地化讀取的用戶提供白名單,不容許其餘用戶使用。一般,這些用也必須被放置在一個特殊的UNIX組中。性能優化

另外,這種本地化短迴路讀取的思路還存在另一個安全問題,客戶端在讀取DataNode數據目錄時打開了一些權限,這樣意味着,擁有這個目錄的權限,那麼其目錄下的子目錄中的數據也能夠被訪問,好比HBase用戶。因爲存在這種安全風險,因此這個實現思路已經不建議使用了。網絡

2.2 方案二:短迴路本地化安全讀取

爲了解決上述問題,在實際讀取中須要很是當心的選擇文件。在UNIX中有這樣一種機制,叫作「文件描述符傳遞」。使用這種機制來實現安全的短迴路本地讀取,而不是經過目錄名稱的客戶端,DataNode打開Block文件和元數據文件,將它們直接給客戶端。由於文件描述符是隻讀的,用戶不能修改文件。因爲它沒有進入Block目錄自己,它沒法讀取任何不該該訪問的目錄。app

舉個例子:dom

現有兩個用戶hbase1和hbase2,hbase1擁有訪問HDFS目錄上/appdata/hbase1文件的權限,而hbase2用戶沒有改權限,可是hbase2用戶又須要訪問這個文件,那麼能夠藉助這種「文件描述符傳遞」的機制,可讓hbase1用戶打開文件獲得一個文件描述符,而後把文件描述符傳遞給hbase2用戶,那麼hbase2用戶就能夠讀取文件裏面的內容了,即便hbase2用戶沒有權限。這種關係映射到HDFS中,能夠把DataNode看做hbase1用戶,客戶端DFSClient看做hbase2用戶,須要讀取的文件就是DataNode目錄中的/appdata/hbase1文件。實現以下圖所示:socket

2.3 緩存文件描述

HDFS客戶端可能會有常常讀取相同Block文件的場景,爲了提高這種讀取性能,舊的短迴路本地讀取實現具備Block路徑的高速緩存。該緩存容許客戶端從新打開其最近已讀取的Block文件,而不須要再去訪問DataNode路徑讀取。oop

新的短迴路本地讀取實現不是一個路徑緩存,而是一個名爲FileInputStreamCache的文件描述符緩存。這樣比路徑緩存要更好一些,由於它不須要客戶端從新打開文件來從新讀取Block,這種讀取方式比就的短迴路本地讀取方式在讀性能上有更好的表現。

緩存的大小能夠經過dfs.client.read.shortcircuit.streams.cache.size屬性來進行調整,默認是256,緩存超時能夠經過dfs.client.read.shortcircuit.streams.cache.expiry.ms屬性來進行控制,默認是300000,也能夠將其設置爲0來將其進行關閉,這兩個屬性均在hdfs-site.xml文件中能夠配置。

2.4 如何配置

爲了配置短迴路本地化讀取,須要啓用libhadoop.so,通常來講所使用Hadoop一般都是包含這些包的,能夠經過如下命令來檢測是否有安裝:

 $ hadoop checknative -a
   Native library checking:
   hadoop: true /home/ozawa/hadoop/lib/native/libhadoop.so.1.0.0
   zlib:   true /lib/x86_64-linux-gnu/libz.so.1
   snappy: true /usr/lib/libsnappy.so.1
   lz4:    true revision:99
   bzip2:  false

短迴路本地化讀取利用UNIX的域套接字(UNIX domain socket),它在文件系統中有一個特定的路徑,容許客戶端和DataNode進行通訊。在使用的時候須要設置這個路徑到Socket中,同時DataNode須要可以建立這個路徑。另外,這個路徑應該不可能被除了hdfs用戶或root用戶以外的任何用戶建立。所以,在實際建立時,一般會使用/var/run或者/var/lib路徑。

短迴路本地化讀取在DataNode和客戶端都須要配置,配置以下:

<configuration>
  <property>
    <name>dfs.client.read.shortcircuit</name>
    <value>true</value>
  </property>
  <property>
    <name>dfs.domain.socket.path</name>
    <value>/var/lib/hadoop-hdfs/dn_socket</value>
  </property>
</configuration>

其中,配置dfs.client.read.shortcircuit屬性是打開這個功能的開關,dfs.domain.socket.path屬性是DataNode和客戶端之間進行通訊的Socket路徑地址,核心指標配置參數以下:

屬性 描述
dfs.client.read.shortcircuit 打開短迴路本地化讀取,默認false
dfs.client.read.shortcircuit.skip.checksum 若是配置這個參數,短迴路本地化讀取將會跳過checksum,默認false
dfs.client.read.shortcircuit.streams.cache.size 客戶端維護一個最近打開文件的描述符緩存,默認256
dfs.domain.socket.path DataNode和客戶端DFSClient通訊的Socket地址
dfs.client.read.shortcircuit.streams.cache.expiry.ms 設置超時時間,用來設置文件描述符能夠被放進FileInputStreamCache的最小時間
dfs.client.domain.socket.data.traffic 經過UNIX域套接字傳輸正常的數據流量,默認false

3.總結

短迴路本地化讀取可以從HDFS層面來提高讀取性能,若是HBase場景中,有涉及到讀多寫少的場景,在除了從HBase服務端和客戶端層面優化外,還能夠嘗試從HDFS層面來進行優化。

4.結束語

這篇博客就和你們分享到這裏,若是你們在研究學習的過程中有什麼問題,能夠加羣進行討論或發送郵件給我,我會盡我所能爲您解答,與君共勉!

另外,博主出書了《Hadoop大數據挖掘從入門到進階實戰》,喜歡的朋友或同窗, 能夠在公告欄那裏點擊購買連接購買博主的書進行學習,在此感謝你們的支持。

相關文章
相關標籤/搜索