1. 程式人生 > >大資料之hbase的寫資料過程詳解

大資料之hbase的寫資料過程詳解

帶著問題來尋找答案:
1.HBASE的讀寫過程就是HBASE的定址過程
2.如何快速的尋找到地址?
3.為什麼hbase可以快速的查詢 寫入資料?
4.Hbase的資料模型:底層儲存的資料到底是怎麼樣的過程 ?
5.Hbase的資料模型設計:資料檔案最終儲存在hdfs的結構是怎麼樣的?並不是key value
客戶端發起寫資料請求
構建Put物件:一個Put物件代表一行資料記錄,可以新增多個列的資料。
如上例所示, RowKey為“012005000201” ,包含3個列:name,gender,address。
Put or PutList?
HBase提供了兩個主要的寫資料介面,一個可以寫入單行資料,即Put介面,另一個可以批量寫入多行資料,即PutList介面。事實上, Put僅是PutList的一種特殊情形。因此,後面的流程介紹僅僅涉及PutList。
找region:


如何快速的找到region?
答:找mata表中的metaregion
我們如何快速的找到我的表的元資料資訊在meta表中哪個metaregion的位置?
答:zookeeper
Meta表的路由資訊:這個表有哪些region 每一個region在哪些位置上
這裡寫圖片描述
不論是讀還是寫,首先是找region
Metaregion
Userregion
資料
為什麼寫入資料需要找region而不是直接追加?
mysql:insert操作 新資料直接追加
mysl的定址過程:一張表對應一個檔案,找到表就是找到檔案,新資料直接追加在末尾

Habse:
在一張表中,region管理一定範圍內的數 rowkey按字典排序
第一個region的start key是空不是0
一張表的不同region可以放到不同的主機中去

Put:資料根據不同的rowkey,插入到不同的region中
當資料量很大時,hbase:meta表也會被拆分成多個 region,稱之為metaregion,也可能會被放到不同的主機上,這些metaregion儲存的就是某一些表的路由資訊,也就是:userregion,region所屬的regionserve資訊

Regionserver內部按照什麼來進行分配資料:rowkey字典排序

資料分組:這裡寫圖片描述
任務交給regionserver之後,regionser做什麼?
資料進入的時候,並不是一條一條的進入的,有可能是很多條,比如list一次來10w條資料,
這麼大的資料,拿到資料以後,有2種處理方式:
1.每一條資料都要建立一次連線,一條一條的寫入資料
2.對資料進行分組,分2次
1分:按照region來分 根據rowkey, 資料分發到不同的region中
2分:存在可能多個region可能在一臺主機regionserver的情況,這種情況就會把幾個相同主機的region放在一起,方便批量處理 根據region分,分發到不同的regionserver中

打比方:圖書館採購書本
先按書的編號分類
再將已經分類的資料分到不同的樓層,同一樓層,批量處理
往RegionServer傳送寫資料請求:也就是說在regionser拿到資料前就進行了資料的分這裡寫圖片描述
1.利用HBase自身封裝的RPC框架,來完成資料傳送操作。往多個RegionServer傳送請求是並行操作。
2.客戶端傳送完寫資料請求後,會自動等待請求處理結果。
3.如果客戶端沒有捕獲到任何的異常,則認為所有的資料都已經被寫入成功。
4.如果全部寫入失敗,或者部分寫入失敗,客戶端能夠獲知詳細的失敗Key值列表。從這裡也可以看出, PutList操作是不保證原子性的。
比如:在mysql中,inseret多條資料,假如最後一條寫入失敗,所有的資料進行資料回滾,這就是原子性操作
Hbase的原子性:
只能夠保證一行的原子性 ,不能保證putlist一次的所有資料原子性,為什麼?
因為Habse對於整體資料沒有原子性,hbase在put資料時,即使後面的資料put失敗,其他的資料還是會正常put進入hdfs,即使再次put相同的資料,hbase資料put自動向下覆蓋,即使多次put相同的資料也不影響 ,只有時間戳可能會不同
什麼是一行資料的原子性?
假如一行資料中有多個欄位,如果不能保證一行資料的原子性,可能會出現部分欄位put進hdfs中,這樣的情況,這條資料就會出問題,因此一行資料的原子性必須要有保證,put成功,一行資料全部成功,否則put失敗

只要第一次的資料進入hdfs開始寫入,後面的資料想寫失敗都很難,為什麼?
因為:資料在寫的時候,所有的資料,已經進入hbase,完成資料的劃分,也就是陣列劃分,劃分到不同的region,region劃分到不同的regionserver

如何獲取hbase寫入hfs之後的回撥函式的值?
在這個值,可以獲取到哪些資料寫入成功,哪些資料寫入失敗
有那種情況,put了多條資料,但是顯示的數量少於put的數量?
欄位名相同的時候,也就是同一個cell,時間戳的最大值會覆蓋其他的值

Region寫資料流程這裡寫圖片描述
這裡寫圖片描述
應用了zookeeper的分散式事務鎖的方式:
1.獲取region鎖 有了這個鎖的region,想要獲取這個有鎖的region的程序必須等待
2.依次獲取各行的鎖:拿到每一行的鎖
3.先將拿到鎖的一行資料,寫入到memstore中,
4.釋放寫入完畢的這一行資料的行鎖
5.寫資料到wal中
6.Memstore和wal都寫入以後,釋放region鎖

Hbase的不同版本,menstore和wal寫入的順序是有差異的
1.0以前的老版本:先寫wal,寫完了以後再寫memstore
新版本:memstore和wal是並行同時寫資料,但是由於memstore’是將資料寫入記憶體中,而wal是將資料寫入hdfs中,因此memstore寫資料的速度要塊,因此memstore先於wal結束,釋放行鎖

為什麼資料通過wal已經寫入到hdfs中了,還要通過memstore再將資料往 記憶體中寫一次呢?
答:是為了資料的寫入和讀取的速度塊
為什麼會有回滾操作機制?
有可能寫入到記憶體成功,但是沒有成功的寫入到hdfs中,比如hdfs的主機掛掉了,沒有寫入成功,就不能正常的釋放鎖,因此就會產生異常,然後啟動回滾的操作,將記憶體的資料也刪除
回滾就會可能出現髒讀的情況:重新整理的速度比釋放鎖的速度塊 ,重新整理了就把記憶體中的資料,立馬寫入到hdfs中 這個可能大概是千萬毫秒分子1
先寫memstore再寫wal的優缺點?
優點:這條資料沒有寫入到hdfs中,使用者就可以訪問了====habse速度快的原因
缺點:髒讀

HBase LSM Tree :這裡寫圖片描述
1.將Put/Delete的資料暫時儲存在每個Region的記憶體中,即MemStore中。寫記憶體,避免多Region情形下帶來的過多的分散IO操作。
2.資料在寫入到MemStore之後,也會順序寫入到HLog中,來保證資料的安全。

為什麼delete的資料會儲存到我們的memstore中?為什麼不是找到資料後直接刪掉?
操作Io是如何刪除一條資料?
先建立一個新檔案,然後將原檔案一行一行的拷貝到新檔案,當讀取到要刪除的一條資料時,跳過不讀取,繼續將剩下的讀取到新檔案,然後將原檔案刪除,將新檔案的名字改成原檔案的名字

邏輯刪除:沒有真正刪除,而是將資料狀態改為關閉
物理刪除:delete從物理層面刪除,刪除資料就不存在了
如何選擇物理刪除?邏輯刪除?對後面的業務有沒有影響
因為:將delete的資料放在memstore,然後把每一個cell標記為刪除,當我們查詢資料時,先在memstore中查詢,如果發現查詢的資料,標記為刪除,就不繼續進行操作,直接返回給使用者,資料不存在
這裡寫圖片描述
存在如下3種場景,會觸發一個Region的Flush操作:
1.該Region的MemStore的總大小,達到了預設的Flush Size閾值。這種場景下的Flush操作,當它把memstore中的資料寫出到hdfs的hfile檔案的時候,在這個時間內,是處於阻塞的狀態,此時不允許寫入資料到memstore。通常僅瞬間堵塞使用者的讀寫操作。但如果超出預設Flush Size閾值過多的話,也可能會引起較長時間的堵塞。

2.RegionServer的總記憶體大小超出了預設的閾值大小。這種場景下,在總記憶體沒有降低到預設的閾值以下之前,可能會較長時間堵塞。 比如:總記憶體可用大小50M,預設定flush值100M,因此50M的時候,就應該要執行flush操作。一般是百分子70,50M的可用空間大小,只有35M的時候,就可以執行flush操作了
3.手動重新整理,立馬寫入hfile

=================因此hfile的大小,很有可能是不一樣的

多HFile的影響這裡寫圖片描述
X:產生hfile的數量
Y:所需時間

總結:這裡寫圖片描述
Compaction合併:
這裡寫圖片描述
1.Compaction的主要目的,是為了減少同一個Region同一個ColumnFamily下面的小檔案數目,從而提升讀取的效能。
2. Compaction分為Minor、 Major兩類:
3. Minor:小範圍的Compaction。有最少和最大檔案數目限制。通常會選擇一些連續時間範圍的小檔案進行合併====小合併
4. Major:涉及該Region該ColumnFamily下面的所有的HFile檔案。刪除的資料。===大合併
5.Minor Compaction選取檔案時,遵循一定的演算法。
Memstore寫出到hfile檔案中,而hfile檔案是在hdfs中,但是hdfs系統,不適合大量的小檔案,而hbase的寫入過程,會產生很多的小檔案,比如手動flush和memstore的總記憶體大小比較小的時候,因此就會產生大量的小檔案:hfile 因此。Hbase引入了合併機制,一是目的是為了節約儲存空間,同時還有處理過期和被標記為刪除的資料
需要刪除的資料包含哪些資料?
1.ttl 帶有有效期的資料,有效期過來之後,不能被訪問,但是仍然存在
2.Put資料:時間戳版本資料數量大於vsrsion可存在的數量
3.需要刪除的資料,將資料標記為刪除
Major和minor合併的區別有哪些?
1.合併範圍不同
小範圍:在一定時間內,將多個小檔案合併在一起,合併的是一部分發hfile
大範圍:將所有的hfile合併
2.功能不同
小範圍:只進行整理
大範圍:刪除只會在大合併的時候執行操作,

一般情況下,不會做大合併!
防止誤區:開啟大合併,整個hbase的所有的hfile要合併,但是並不是所有的hfile合併成一個hfile,而是一個列族當中的所有的hfile合併成一個hfile,所有的列族開始合併操作

很少做大合併,為什麼?
工程量過大
如果一定要大合併呢?
對於某一張表的某些列族,手動執行大合併,不建議開啟大合併!!!

為什麼不建議開啟大合併?
因為在執行大合併的時候,整個hbase的hfile都在參與合併,整個hbase會鎖住,此時讀資料和寫資料都不行
為什麼可以做到不執行大合併操作來達到增加空間呢?
因為hbase的底層是hdfs,如果空間不夠,可以任意的增加硬碟,增加伺服器
Split :這裡寫圖片描述
1.當我們合併之後,region會變的很大,rowkey的範圍變的很大,因此錯split
2.在region分裂成兩個region時,真正的資料沒有移動,產生一個新的管理者的時間,比直接把需要移動的資料全部移動過去的時間會少很多,但是需要移動的資料,不可能永遠在原region中,因為新region不可能永遠的跨伺服器去取資料,這樣會嚴重影響我們的查詢速度,
Master會做負載均衡操作,會將原region中需要移動的資料,移動到新的region中去,
切分時:A原來的資料,還是在A,只是為了B檔案引用,B並沒有拿到資料
什麼時候給新region資料?
客戶端所快取的父Region的路由資訊需要被更新之後,master做負載均衡:將原regionA中需要移動的資料,交給切後出的B 這裡的資料是region資料,不是hdfs資料

資料本地化 減少網路連線,提高效率

原來的region,rowkey是空到空,切分了以後,A和B各自管理各自的資料,
新切出的B有資料, 當我們有多臺主機的時候,hmaster將父regionA放到A主機中,將子regionB放到B主機中,有什麼好處?
假如Aregion的資料存放在hdfs的A主機,在切分的時候,切成時hdfs的資料沒有移動,也就是region資訊由Bregion來管理,但是hdfs上的資料沒有移動到B主機上去

其實,hbase的寫分2個步驟:
尋regionserver的過程
Regionserver內部處理過程