[ 版權申明:本文系作者原創,轉載請注明出處]
文章出處: http://blog.csdn.net/sdksdk0/article/details/51680296
作者: 朱培 ID:sdksdk0
-----------------------------------------------------------------------------------
一、HBase簡介
1.1簡介
hbase是bigtable的開源山寨版本。是建立的hdfs之上,提供高可靠性、高性能、列存儲、可伸縮、實時讀寫的數據庫系統。
它介於nosql和RDBMS之間,僅能通過主鍵(row key)和主鍵的range來檢索數據,僅支持單行事務(可通過hive支持來實現多表join等復雜操作)。主要用來存儲非結構化和半結構化的松散數據。與hadoop一樣,Hbase目標主要依靠橫向擴展,通過不斷增加廉價的商用服務器,來增加計算和存儲能力。
HBase以表的形式存儲數據。表有行和列組成。列划分為若干個列族(row family)。
1.2 Hbase與傳統數據庫的對比
我們可以先來看一下傳統的關系型數據庫中的表:

然后與HBase的表進行對比,hbase的表結構,與傳統的關系型數據庫有較大的差別

我們就可以發現很多不同地方:
hbase不支持sql語句,它是一個nosql的一種,如果沒有學過nosql或rubey,我們可以用help
1、定義表時不指定字段
2、定義表的時候只要指定列族名,列族數量不限
3、每一行都有一個固定的字段(行鍵),具有唯一性
4、對值的修改,原來的值是保留着的,每個值可以保留多個版本。默認查詢的是最新版本的的值。(默認保留一個版本)
1.3 HBase中的重要概念
列族:hbase表中的每個列,都歸屬與某個列族。列族是表的chema的一部分(而列不是),必須在使用表之前定義。列名都以列族作為前綴。例如courses:history , courses:math 都屬於 courses 這個列族。
訪問控制、磁盤和內存的使用統計都是在列族層面進行的。實際應用中,列族上的控制權限能幫助我們管理不同類型的應用:我們允許一些應用可以添加新的基本數據、一些應用可以讀取基本數據並創建繼承的列族、一些應用則只允許瀏覽數據(甚至可能因 為隱私的原因不能瀏覽所有數據)。
時間戳:HBase中通過row和columns確定的為一個存貯單元稱為cell。每個 cell都保存着同一份數據的多個版本。版本通過時間戳來索引。時間戳的類型是 64位整型。時間戳可以由hbase(在數據寫入時自動 )賦值,此時時間戳是精確到毫秒的當前系統時間。時間戳也可以由客戶顯式賦值。如果應用程序要避免數據版本沖突,就必須自己生成具有唯一性的時間戳。每個 cell中,不同版本的數據按照時間倒序排序,即最新的數據排在最前面。
為了避免數據存在過多版本造成的的管理 (包括存貯和索引)負擔,hbase提供了兩種數據版本回收方式。一是保存數據的最后n個版本,二是保存最近一段時間內的版本(比如最近七天)。用戶可以針對每個列族進行設置。
Cell:由{row key, column( =<family> + <label>),version} 唯一確定的單元。cell中的數據是沒有類型的,全部是字節碼形式存貯。
二、HBase體系結構
2、每一個region內部還要一句列族划分為若干個HStore
3、每個HStore中的數據會落地到若干個HFILE文件中
4、region體積會隨着數據插入而不斷增長,到一定閾值后悔分裂
5、隨着region的分裂,一台regionserver上管理的region會越來越多
6、HMASTER會根據regionserver上管理的region數做負載均衡
7、region中的數據擁有一個內存緩存:memstore,數據的訪問優先在memstore中進行
8、memstore中的數據因為空間有限,所以需要定期flush到文件storefile中,每次flush都是生成新的storefile
9、storefile的數量隨着時間也會不斷增加,regionserver會定期將大量storefile進行合並(merge)
行鍵的設計對數據查詢效率的影響非常大。
hbase可以作為一個線上系統的底層系統的功能。
Hmaster可以做負載均衡,監控到各個節點之間的數據存儲情況。
每一個store(列族)會有一個內存緩存,存放的是一些最熱的數據(最近訪問的),這樣的話讀取數據的速度會快很多。
文件都是有索引的,所以查起來會比較快的。
region會在storefile定期進行合並操作。
三、HBase環境搭建
export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64 export HBASE_MANAGES_ZK=false
在hbase-site.xml中,主要就是配置hdfs的主機地址,還有下面的ubuntu1,2,3就是zookeeper的主機名個端口2181,不同的機器可以酌情配置。
configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://ubuntu2:9000/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>ubuntu1:2181,ubuntu2:2181,ubuntu3:2181</value>
</property>
</configuration>
3、最后修改regionservers,將默認的localhost修改為主機的地址,這個配置文件的意思就是設置從節點,和我們之前配置的hadoop集群都是差不多的,就相當於那個salver。
ubuntu1 ubuntu2 ubuntu3
首先啟動zk集群
./zkServer.sh start
啟動hbase集群
start-dfs.sh
啟動hbase,在主節點上運行:
start-hbase.sh
2、 通過瀏覽器訪問hbase管理頁面
192.168.44.131:60010
3、 為保證集群的可靠性,要啟動多個HMaster
hbase-daemon.sh start master
jps在主節點上面的效果是:會啟動HRegionServer和HMaster
四、HBase shell的使用
4.1 啟動
bin/hbase shell我們首先來show database一下,從圖片上面,我們可以看到有錯誤,也即使說hbase不支持sql的語法,這點我們前面已經說到了。那么我們就可以輸入help命令來查看hbase的基本語句語法了。
4.2 建表
Examples:
hbase> create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40']
hbase> create 't1', 'f1', SPLITS => ['10', '20', '30', '40']
hbase> create 't1', 'f1', SPLITS_FILE => 'splits.txt', OWNER => 'johndoe'
hbase> create 't1', {NAME => 'f1', VERSIONS => 5}, METADATA => { 'mykey' => 'myvalue' }
hbase> # Optionally pre-split the table into NUMREGIONS, using
hbase> # SPLITALGO ("HexStringSplit", "UniformSplit" or classname)
hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit', CONFIGURATION => {'hbase.hregion.scan.loadColumnFamiliesOnDemand' => 'true'}}
那么我們就以例子為准,來新建一個用戶信息表。表名為user-info,包含兩個列族(base_info和extra_info),保留3個版本。
create 'user-info',{NAME=>'base_info',VERSIONS=>3},{NAME=>'extra_info'}
4.3 插入
put 'user-info','rk-100001','base_info:name','張s' put 'user-info','rk-100001','base_info:age','20' put 'user-info','rk-100001','base_info:address','湖南長沙'
在hbase只能一條條的插入,就比如一次只能插入name,那么如果我們想插入age,address就需要一個個的put。
4.4 查詢
scan 'user-info'
如果我再插入一行,
put 'user-info','rk100003','base_info:name','angelabby'
一行中的所有字段名+字段值,在存儲的時候,hbase會排序,排序的依據是按照K的字典順序,所有的行也會有序存儲,排序的依據是rowkey的字典順序。
這個特性會影響連續存放。
get 'user-info','rk100003'
4.5 修改
put 'user-info','rk100003','base_info:name',’yangying' put 'user-info','rk100003','base_info:name','baobao'
scan 'user-info',{VERSIONS=>10}
4.6 刪除
需要先禁用這個表,然后才可以drop掉。 disable 'user-info' drop 'user-info'
五、eclipse中使用HBase
打開eclipse,導入hbase/lib中的所有包。然后就可以愉快的開始寫了,這里以在eclipse中庸hbase建表和插入數據為例:
//建表,DDL操作
public static void main(String[] args) throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
// Configuration conf=new Configuration();
//會加載hbase-site.xml配置文件
Configuration conf=HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum","ubuntu1:2181,ubuntu2:2181,ubuntu3:2181");
HBaseAdmin admin=new HBaseAdmin(conf);
TableName name = TableName.valueOf("user-info");
HTableDescriptor tableDescriptor=new HTableDescriptor(name);
//創建列名
HColumnDescriptor base_info = new HColumnDescriptor("base_info");
//給列族增加版本約束
base_info.setMaxVersions(3);
//將列族添加到表描述對象中
tableDescriptor.addFamily(base_info);
//用createTable方法創建一個tabelDescriptor所描述的對象
admin.createTable(tableDescriptor);
//關閉連接
admin.close();
}
然后來插入數據:
@Test
//插入數據,屬於DML操作
public void Put() throws IOException{
Configuration conf=HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum","ubuntu1:2181,ubuntu2:2181,ubuntu3:2181");
HTable hTable = new HTable(conf,"user-info");
Put put=new Put(Bytes.toBytes("rk-10001"));
put.add("base_info".getBytes(),"name".getBytes(),"wangming".getBytes());
put.add("base_info".getBytes(),"age".getBytes(),"20".getBytes());
hTable.put(put);
hTable.close();
}
最后我們可以在hbase的shell窗口來查看表是否已插入好數據。

到此,HBase的環境配置及其基本的使用以及分享完畢!如果想進一步學習相關知識,歡迎關注,如果對Hbase有什么疑問的地方歡迎留言!
HBase非常適用於大量的數據存儲,因為它是一張非常大的表,可以有無數個列族,可以不斷的擴展,這個特點是傳統的mysql,oracle等關系型數據庫是無法比擬的!
