老劉目前為明年校招而努力,寫文章主要是想用大白話把自己複習的大資料知識點詳細解釋出來,拒絕資料上的生搬硬套,做到有自己的理解!
01 HBase知識點(3)
第13點:HBase表的熱點問題
什麼是熱點問題?
就是我們檢索hbase的資料首先要通過rowkey來定位資料行,但是呢這裡面就有一個問題,由於rowkey設計的問題,就會導致表的資料可能只分布在hbase叢集中的一個或少數節點。
當大量客戶端訪問hbase叢集這些資料時,就會造成少數RegionServer的讀寫請求過多,負載過大,而其他的RegionServer負載卻很小,就造成了熱點現象。
詳細說說出現熱點問題的原因?
① hbase中的資料是按字典序排序的,當大量連續的rowkey集中寫在個別的region,各個region之間資料分佈不均衡。
② 建立表時沒有提前預分割槽,建立的表預設只有一個region,大量的資料寫入當前的region。
③ 建立表已經提前預分割槽了,但設計的rowkey沒有規律可循,設計的rowkey沒有加雜湊欄位。
熱點問題的解決方案
預分割槽
預分割槽的目的讓表的資料可以均衡的分散在叢集中,而不是預設只有一個region分佈在叢集的一個節點上。
加鹽
具體就是給rowkey分配一個隨機字首以使得它和之前的rowkey的開頭不同。
第14點:rowkey設計
在第13點已經說過rowkey設計不好,會出現熱點問題。所有那rowkey到底該如何設計呢?
rowkey設計有三個原則,這個不是我定的,我看資料上這樣寫的。
首先是rowkey長度原則,它的設計建議儘可能短,又不能太短,否則rowkey之間的字首重複的概率增大,因為rowkey按照字典序排序,這些資料會盡量的儲存在一起。
其次是rowkey雜湊原則,就是給rowkey增加一些隨機字首,讓rowkey儘量不一樣,儘量避免出現熱點問題。
最後是rowkey唯一原則,就是必須保持它唯一。
第15點:HBase的資料備份
老劉知道的HBase資料備份有兩種,第一種是使用HBase提供的類把HBase中某張表的資料匯出到HDFS,之後有需要就可以匯出到HBase的表中。
① 從HBase表匯出到HDFS中
hbase org.apache.hadoop.hbase.mapreduce.Export myuser /hbase_data/myuser_bak
② 有需要了,就在HBase中建立備份的目標表
create 'myuser_bak','f1','f2'
③ 再把HDFS上的資料匯入到備份目標表
hbase org.apache.hadoop.hbase.mapreduce.Driver import myuser_bak /hbase_data/myuser_bak/
就這樣第一種方法就講完了,在講講第二種方法利用snapshot快照進行表的備份,網上資料說通過snapshot快照的方式實現HBase資料的遷移和拷貝是最為推薦的資料遷移方式,老劉對這個方法不是很懂,等以後在好好講講,這一次就先提一提,讓大家有個印象。
第16點:HBase二級索引
為什麼需要二級索引?
① 對於HBase而言呢,如果想精度定位到某行記錄,唯一的方法是通過rowkey來查詢,但是你不通過rowkey來查詢資料,就必須進行全表掃描。對於較大的表,全表掃描的代價太大了,就需要另尋方法了。
很多情況下,我們需要從多個方面查詢資料。例如,在定位某個學生的資訊,可以通過姓名、身份證號、學號等不同方面來查詢,但是把這麼多方面的資料都放到rowkey中幾乎不可能(業務的靈活性不允許,對rowkey長度的要求也不允許)。
所以需要secondary index(二級索引)來完成這件事。
② 也是為了讓HBase的查詢更加高效,比如使用非rowkey欄位檢索也能做到秒級響應,就可以需要在HBase上面構建二級索引。
那如何構建二級索引?
推薦用phoenix(菲尼克斯)構建二級索引,老劉簡單講講phoenix的概念。
它建立索引有兩種:
① 全域性索引,適用於讀多寫少的業務場景。
使用全域性索引在寫資料的時候開銷很大,因為所有對資料表的更新操作,都會引起索引表的更新,而索引表是分佈在不同的資料節點上的,跨節點的資料傳輸帶來了較大的效能消耗。
在讀資料的時候Phoenix會選擇索引表來降低查詢消耗的時間。在預設情況下如果想查詢的欄位不是索引欄位的話,索引表就不會被使用,也就是說不會有查詢速度的提升。
② 本地索引,適用於寫操作頻繁以及空間受限制的場景。
與全域性索引一樣,Phoenix會自動判定在進行查詢的時候是否使用索引。
使用本地索引時,索引資料和資料表的資料存放在相同的伺服器中,這樣避免了在寫操作的時候往不同伺服器的索引表中寫索引帶來的額外開銷。
使用本地索引的時候即使查詢的欄位不是索引欄位,索引表也會被使用,這會帶來查詢速度的提升,這點跟全域性索引不同。
第17點:HBase的namespace
namespace的概念
在HBase中,namespace就相當於關係型資料庫中的database,它是指對一組表的邏輯分組,就是同一組中的表有類似用途的意思。那就相當於說我們利用namespace可以很方便對錶在業務上進行劃分。
namespace基本操作
建立namespace hbase>create_namespace 'nametest' 檢視namespace hbase>describe_namespace 'nametest' 列出所有namespace hbase>list_namespace 在namespace下建立表 hbase>create 'nametest:testtable', 'fm1' 檢視namespace下的表 hbase>list_namespace_tables 'nametest' 刪除namespace hbase>drop_namespace 'nametest'
第18點:HBase的資料版本的確界以及TTL
在HBase當中,我們可以為資料設定上界和下界,這個其實就是定義資料的歷史版本保留多少個,我們通過自定義歷史版本儲存的數量,可以實現資料多個歷史版本的資料查詢
版本的下界
預設的版本下界是0,即禁用。row版本使用的最小數目是與生存時間(TTL Time To Live)相結合的,並且我們根據實際需求可以有0或更多的版本,使用0,即只有1個版本的值寫入cell。
版本的上界
之前預設的版本上界是3,也就是一個row保留3個副本,現版本已預設為1。
資料的TTL
在實際工作當中經常會遇到有些資料過了一段時間我們可能就不需要了,那麼這時候我們可以使用定時任務去定時的刪除這些資料
或者我們也可以使用Hbase的TTL(Time To Live)功能,讓我們的資料定期的會進行清除。
下面老劉將寫程式碼來設定資料的確界以及設定資料的TTL:
public class HBaseVersionsAndTTL { public static void main(String[] args) throws IOException { //獲得連線 Configuration configuration = HBaseConfiguration.create(); configuration.set("hbase.zookeeper.quorum", "node01:2181,node02:2181,node03:2181"); //建立連線物件 Connection connection = ConnectionFactory.createConnection(configuration); //建表的時候用Admin Admin admin = connection.getAdmin(); if(!admin.tableExists(TableName.valueOf("version_hbase"))) { //新增表名資訊 HTableDescriptor version_hbase = new HTableDescriptor(TableName.valueOf("version_hbase")); HColumnDescriptor f1 = new HColumnDescriptor("f1"); //最大版本、最小版本、TTL f1.setMinVersions(3); f1.setMaxVersions(5); f1.setTimeToLive(30);//30s version_hbase.addFamily(f1); admin.createTable(version_hbase); } //插入資料 Table version_hbase = connection.getTable(TableName.valueOf("version_hbase")); for(int i = 0; i < 6; i++) { Put put = new Put("001".getBytes()); put.addColumn("f1".getBytes(), "name".getBytes(), ("zhangsan" + i).getBytes()); version_hbase.put(put); } //查詢 Get get = new Get("001".getBytes()); //設定最大版本 get.setMaxVersions(); Result result = version_hbase.get(get); Cell[] cells = result.rawCells(); for(Cell cell: cells) { System.out.println(Bytes.toString(CellUtil.cloneValue(cell))); } //關閉連線 admin.close(); version_hbase.close(); connection.close(); } }
02 HBase總結
好啦,大資料HBase的知識點總結的差不多了,內容比較多,大家需要仔細理解,爭取做到用自己的話把這些知識點講述出來。
最後,如果覺得有哪裡寫的不好或者有錯誤的地方,可以聯絡公眾號:努力的老劉,進行交流哦!希望能夠對大資料開發感興趣的同學有幫助,希望能夠得到同學們的指導。