Hbase寫數據,存數據,讀數據的詳細過程 分類: B7_HBASE 2015-03-15 20:11 117人閱讀 評論(0) 收藏

Client寫入 -> 存入MemStore,一直到MemStore滿 -> Flush成一個StoreFile,直至增加到必定閾值 -> 出發Compact合併操做 -> 多個StoreFile合併成一個StoreFile,同時進行版本合併和數據刪除 -> 當StoreFiles Compact後,逐步造成愈來愈大的StoreFile -> 單個StoreFile大小超過必定閾值後,觸發Split操做,把當前Region Split成2個Region,Region會下線,新Split出的2個孩子Region會被HMaster分配到相應的HRegionServer 上。

Hbase寫數據和存數據的過程

Hbase寫數據,存數據,讀數據的詳細過程

 

Client寫入 -> 存入MemStore,一直到MemStore滿 -> Flush成一個StoreFile,直至增加到必定閾值 -> 出發Compact合併操做 -> 多個StoreFile合併成一個StoreFile,同時進行版本合併和數據刪除 -> StoreFiles Compact後,逐步造成愈來愈大的StoreFile -> 單個StoreFile大小超過必定閾值後,觸發Split操做,把當前Region Split2RegionRegion會下線,新Split出的2個孩子Region會被HMaster分配到相應的HRegionServer 上,使得原先1Region的壓力得以分流到2Region上由此過程可知,HBase只是增長數據,有所得更新和刪除操做,都是在Compact階段作的,因此,用戶寫操做只須要進入到內存便可當即返回,從而保證I/O高性能。算法

對上述流程的補充:

補充1HStore存儲是HBase存儲的核心,其中由兩部分組成,一部分是MemStore,一部分是StoreFiles數據庫

補充2HLog的功能:緩存

在分佈式系統環境中,沒法避免系統出錯或者宕機,一旦HRegionServer之外退出,服務器

MemStore中的內存數據就會丟失,引入HLog就是防止這種狀況。多線程

工做機制:每 個HRegionServer中都會有一個HLog對象,HLog是一個實現Write Ahead Log的類,每次用戶操做寫入Memstore的同時,也會寫一份數據到HLog文件,HLog文件按期會滾動出新,並刪除舊的文件(已持久化到 StoreFile中的數據)。當HRegionServer意外終止後,HMaster會經過Zookeeper感知,HMaster首先處理遺留的 HLog文件,將不一樣regionlog數據拆分,分別放到相應region目錄下,而後再將失效的region(帶有剛剛拆分的log從新分配,領取到這些region的 HRegionServerLoad Region的過程當中,會發現有歷史HLog須要處理,所以會Replay HLog中的數據到MemStore中,而後flushStoreFiles完成數據恢復。分佈式

補充3Region就是StoreFilesStoreFiles裏由HFile構成,Hfile裏由hbasedata塊構成,一個data塊裏面又有不少keyvalue對,每一個keyvalue裏存了咱們須要的值。性能

補充4測試

Hbase寫數據,存數據,讀數據的詳細過程

咱們觀察上面這一幅圖:優化

一 張表,有兩個列族(紅顏色的一個,黃顏色的一個),一個列族有兩個列,從圖中能夠看出,這就是列式數據庫的最大特色,同一個列族的數據在在一塊兒的,咱們還 發現若是是有多個版本,同時也會存多個版本。最後咱們還發現裏面存了這樣的值:r1:鍵值,cf1:列族的名字,c1:列明。t1:版本號,value值 (最後一幅圖說明的是value值能夠存放的位置)。經過這樣的見解,咱們發現若是咱們設計表的時候把這幾個東西:r1:鍵值,cf1:列族的名 字,c1:列明的名字取短一點是否是咱們會省出好多存儲的空間!spa

還有,咱們從這一幅圖中還應該獲得這樣的認識

我 們看倒數第二張圖,字段篩選的效率從左到右明顯降低,因此在keyvalue的設計時用戶能夠考慮把一些重要的篩選信息左移到合適的位置,從而在不改變數 據量的狀況下,提升查詢性能。那麼簡單的說就是用戶應當儘可能把查詢維度或信息存儲在行健中,由於它篩選數據的效率最高。

獲得上面的認識後,咱們應該還要會有這樣的覺悟:

HBase 的數據存儲時會被有順序的存儲到一個特定的範圍,由於咱們存儲的時候通常都是按順序的,因此會一直存到同一個region上,因爲一個region只能由 一個服務器管理,這樣咱們總是添加到同一個region上,會形成讀寫熱點,從而使集羣性能降低。那麼解決這個的辦法仍是有的,我能想到的就是,好比咱們 有9臺服務器,那麼咱們就回去當前時間,而後摸9,加到行健前綴,這樣就會被平均的分到不一樣的region服務器上了,這樣帶來的好處是,由於相連的數據 都分佈到不一樣的服務器上了,用戶能夠多線程並行的讀取數據,這樣查詢的吞吐量會提升。

關於咱們版本的控制,咱們要麼就讓多臺服務器上的時間都同步,要麼乾脆就在put插入數據的時候,就設置一個客戶端的時間戳來代替。(由於咱們要是不顯示的添加,人家就給咱們在本身的服務器上添加了本身的時間了。)

補充5:

設 計表的時候,有兩種設計方式,一種是高表設計,一種是胖表設計。根據HBase的拆分規則,咱們的高表設計更容易拆分(使用組合鍵),不過,若是咱們設計 成胖表,而咱們的這個胖裏的數據須要常常修改,這樣設計是很合理的,由於咱們的HBase保證了行級的原子性,若是設計成高表,反而就不合適了,由於不能 保證跨行的原子性。

補充6:

寫緩存

每 一個put的操做其實是RPC的操做,它將客戶端的數據傳送到服務器而後返回,這隻適合小數據量的操做,若是有個應用程序須要每秒存儲上千行數據到 HBase表中,這樣處理就不太合適了。HBase的API配備了一個客戶端的寫緩衝區,緩衝區負責收集put操做,而後調用RPC操做一次性將put送 往服務器。默認狀況下,客戶端緩衝區是禁止的。能夠經過自動刷寫設置爲FALSE來激活緩衝區。 table.setAutoFlush(false);void flushCommits () throws IOException這個方法是強制 將數據寫到服務器。用戶還能夠根據下面的方法來配置客戶端寫緩衝區的大小。 void setWritaeBufferSize(long writeBufferSize) throws IOException;默認大小是 2MB,這個也是適中的,通常用戶插入的數據不大,不過若是你插入的數據大的話,可能要考慮增大這個值。從而容許客戶端更高效地必定數量的數據組成一組通 過一次RPC請求來執行。給每一個用戶的HTable設置一個寫緩衝區也是一件麻煩的事,爲了不麻煩,用戶能夠在

Hbase-site.xml中給用戶設置一個較大的預設值。

<property>

<name>hbase.client.write.buffer</name>

<value>20971520</value>

</property>

補充7:

hbase支持大量的算法,而且支持列族級別以上的壓縮算法,除非有特殊緣由,否則咱們應該儘可能使用壓縮,壓縮一般會帶來較好的 性能。經過一些測試,咱們推薦使用SNAPPY這種算法來進行咱們hbase的壓縮。

Hbase讀數據:

client->zookeeper->.ROOT->.META-> 用戶數據表zookeeper記錄了.ROOT的路徑信息(root只有一個region),.ROOT裏記錄了.META的region信息, (.META可能有多個region),.META裏面記錄了region的信息。

補充1:

在 HBase中,全部的存儲文件都被劃分紅了若干個小存儲塊,這些小存儲塊在get或scan操做時會加載到內存中,他們相似於RDBMS中的存儲單元頁。 這個參數的默認大小是64K。經過以上方式設置:void setBlocksize(int s);(HBase中Hfile的默認大小就是64K跟 HDFS的塊是64M不要緊)HBase順序地讀取一個數據塊到內存緩存中,其讀取相鄰的數據時就能夠再內存中讀取而不須要從磁盤中再次讀取,有效地減小 了磁盤I/O的次數。這個參數默認爲TRUE,這意味着每次讀取的塊都會緩存到內存中。可是,若是用戶順序讀取某個特定的列族,最好將這個屬性設置爲 FALSE,從而禁止使用緩存快。上面這樣描述的緣由:若是咱們訪問特定的列族,可是咱們仍是啓用了這個功能,這個時候咱們的機制會把咱們其它不須要的列 族的數據也加載到了內存中,增長了咱們的負擔,咱們使用的條件是,咱們獲取相鄰數據。 void setBlockCacheEnabled(boolean blockCacheEnable);

補充2:

1:禁止自動刷寫。

咱們有大批數據要插入時,若是咱們沒有禁止,Put實例會被逐個的傳送到regio服務器

,若是用戶禁止了自動刷寫的功能,put操做會在寫緩衝區被填滿時纔會被送出。

2:使用掃描緩存。

若是HBase被用做一個mapreduce做業的輸入源,請最好將做爲mapreduce做業輸入掃描

器實例的緩存用setCaching()方法設置爲比默認值1更大的數。使用默認值意味着map

任務會在處理每條記錄時都請求region服務器。不過,這個值要是500的話,則一次

可傳送500條數據到客戶端進行處理,固然了這數據也是根據你的狀況定的。

這個是行級的,在咱們的119頁有說明。

3:限定掃描範圍。

這個是很好理解的,好比咱們要處理大量行(特別是做爲mapreduce的輸入源),其中

用到scan的時候咱們有Scan.addFamily();的方法,這個時候咱們若是隻是須要到

這個列族中的幾個列,那麼咱們必定要精確。由於過多的列會致使效率的損失。

4:關閉resultScanner

固然了這個不能提升咱們的效率,可是若是沒關就會對效率有影響。

5:塊緩存的用法

首先咱們的塊緩存是經過Scan.setCacheBolcks();的啓動的,那些被頻繁訪問的行

咱們應該使用緩存塊,可是mapreduce做業使用掃描大量的行,咱們就不應使用這個

了。(這個塊緩存跟我在第四節中提到的那個塊是不同的)。

6:優化獲取行健的方式

固然用這個的前提是,咱們只須要表中的行健時,才能用。那麼怎麼用在411頁有說明。

7:關閉Put上的WAL

書上是這麼說,可是我我的以爲這個功能仍是不用的好,由於咱們關閉了這個功能,

服務器就不會把put寫入到WAL,而是直接寫到memstore裏,這樣一旦服務器出現故障

咱們的數據就丟失了。

相關文章
相關標籤/搜索