天天看點

Hadoop學習筆記(四):HBase

hbase是在一個hdfs上開發的面向列的分布式資料庫。hbase不是關系型資料庫,不支援sql。

htable一些基本概念

row key

行主鍵, hbase不支援條件查詢和order by等查詢,讀取記錄隻能按row key(及其range)或全表掃描,是以row key需要根據業務來設計以利用其存儲排序特性(table按row key字典序排序如1,10,100,11,2)提高性能。

column family(列族)

在表建立時聲明,每個column family為一個存儲單元。在上例中設計了一個hbase表blog,該表有兩個列族:article和author。

column(列)

hbase的每個列都屬于一個列族,以列族名為字首,如列article:title和article:content屬于article列族,author:name和author:nickname屬于author列族。

column不用建立表時定義即可以動态新增,同一column family的columns會群聚在一個存儲單元上,并依column key排序,是以設計時應将具有相同i/o特性的column設計在一個column family上以提高性能。

timestamp

hbase通過row和column确定一份資料,這份資料的值可能有多個版本,不同版本的值按照時間倒序排序,即最新的資料排在最前面,查詢時預設傳回最新版本。如上例中row key=1的author:nickname值有兩個版本,分别為1317180070811對應的“一葉渡江”和1317180718830對應的“yedu”(對應到實際業務可以了解為在某時刻修改了nickname為yedu,但舊值仍然存在)。timestamp預設為系統目前時間(精确到毫秒),也可以在寫入資料時指定該值。

value

每個值通過4個鍵唯一索引,tablename+rowkey+columnkey+timestamp=>value,例如上例中{tablename=’blog’,rowkey=’1’,columnname=’author:nickname’,timestamp=’ 1317180718830’}索引到的唯一值是“yedu”。

存儲類型

tablename 是字元串

rowkey 和 columnname 是二進制值(java 類型 byte[])

timestamp 是一個 64 位整數(java 類型 long)

value 是一個位元組數組(java類型 byte[])。

shell操作

  hbase提供了豐富的通路接口,其中hbase shell是常用的便捷方式。

     • hbase shell

     • java clietn api

     • jython、groovy dsl、scala

     • rest

     • thrift(ruby、python、perl、c++…)

     • mapreduce

     • hive/pig

   建立表

<code>&gt; create 'test','data1','data2'</code>

   column family是schema的一部分,而column不是。這裡的data1和data2是column family。

   增加記錄

<code>&gt;put 'test','1','data1:name','luc' &gt;put 'test','1','data1:age','24' &gt;put 'test','1','data2:height','170cm' &gt;put 'test','1','data2:weight','65kg' &gt;put 'test','1','data1:nickname','vichao'</code>

 column完全動态擴充,每行可以有不同的columns。(ps:好像有點胖啊,要減肥~~)

   根據rowkey查詢

<code>&gt; get 'test','1'</code>

htable按rowkey字典序(1,10,100,11,2)自動排序,每行包含任意數量的columns,columns按columnkey(data1:age,data1:name,data1:nickname,data2:height,data2:weight)自動排序。

   更新操作

查詢值:

<code>&gt; </code>get 'test','1','data1:nickname'

更新nickname為'vic':

<code>&gt; </code>put 'test','1','data1:nickname','vic'

查詢更新後的結果:(傳回的将是vic)

<code>&gt; get ‘blog’,’1’,’data1:nickname’</code>

知識點回顧:查詢預設傳回最近的值。

查詢nickname的多個(本示例為2個)版本值

<code>&gt; get 'test','1',{column =&gt; 'data1:nickname',versions =&gt; 2}</code>

知識點回顧:每個column可以有任意數量的values,按timestamp倒序自動排序。

如何隻查詢到以前的舊版本呢,需要借助timestamp

<code>&gt;</code>get 'test','1',{column=&gt;'data1:nickname',timestamp=&gt;1373707746997}

知識點回顧:tabelname+rowkey+column+timestamp=&gt;value

  删除記錄

delete隻能删除一個column

<code>&gt;delete 'test','1','data1:nickname'</code>

删除rowkey的所有column用deleteall

<code>&gt;deleteall 'test','1'</code>

   删除表

練習完畢,把練習表删了吧,删除之前需要先disable

<code>&gt;disable 'test' &gt;drop 'test'</code>

java api操作

    javaapi操作還是比較簡單的,各種api類和api函數,直接上代碼了

      這裡要注意的一點是連接配接到hbase需要将将hbase環境的hbase-site.xml檔案引入到工程中,就像jdbc的資料庫連接配接一樣,不然是連不上hbase滴。

hbase mapreduce操作

     直接上代碼了:

 優化

       針對行的鍵按資料排列的次序進行随機處理;

       每個任務隻執行個體化一個htable對象;

       htable.put(put)執行put操作時不使用任何緩沖。可以通過使用htable.setautoflush(false),設定禁用自動刷入,并設定寫緩沖大小,同時在任務的最後設定htable.flushcommits()或者htable.close(),以確定緩沖中最後沒有剩下的未刷入的資料;

       設計行鍵的時候要多加考慮,可以使用複合鍵,如果鍵是整數,則應該使用二進制形式以節省存儲空間;

hbase和rdbms的比較

       hbase:       

       hbase是一個分布式的面向列的資料存儲系統;

       hbase表可以很高和很寬(數十億行,數百萬列);

       水準分區并在數千個商用機節點上自動複制;

       表的模式是實體存儲的直接反映;

       不支援sql;

       不需要強一緻性和參照完整性;

       不支援索引;行是順序存儲的,每行中的列也是,不存在索引膨脹的問題,插入性能和表的大小無關

      事務好像僅僅支援針對某一行的一系列put/delete操作。不同行、不同表間的操作是無法放在一個事務中的;

       hbase不支援條件查詢和order by等查詢,讀取記錄隻能按row key(及其range)或全表掃描;

      沒有内置對連接配接操作的支援,但是由于表的寬度可以很大,一個寬行可以容下一個主鍵相關的所有資料,并不需要使用連接配接;

       rdbms:

       支援sql;

       需要強一緻性和參照完整性;

       支援事務,索引等;

hbase的特性

      沒有索引,行是順序存儲的,每行中的列也是,不存在索引膨脹的問題,插入性能和表的大小無關;

      自動分區,在表增長的時候,表會自動分裂成區域,并分布到可用的節點上;

      線性擴充和對于新節點的自動處理,增加一個節點,把它指向現有的叢集,并運作regionserver,區域會自動重新進行平衡,負載會均勻分布;

      普通商用硬體支援;

      容錯,大量節點意味着每個節點的重要性并不突出,不用擔心單個節點失效;

      批處理,支援mapreduce操作,可以用全并行的分布式作業來處理資料;