hadoop——hbase

  1. 云栖社区>
  2. 博客>
  3. 正文

hadoop——hbase

sunt_dota 2016-11-21 17:30:00 浏览722
展开阅读全文

一:hbase介绍:

1.介绍:

hbase,hadoop家族一员,是一个开源的,分布式的,面向对象,非结构化数据的存储系统。

hbase存储基于列而不基于行。而且存储的是松散型数据模式。

Hbase 就是 NoSQL 中卓越的一员,Hbase 提供了键值 API,承诺强一致性,所以客户端能够在写入后马上看到数据。

HBase 依赖 Hadoop 底层分布式存储机制,因此能够运行在多个节点组成的集群上,并对客户端应用代码透明,从而对每个开发人员来说设计和开发 Hbase 的大数据项目变得简单易行。

Hbase 被设计来处理 TB 到 PB 级的数据,并针对该类海量数据和高并发访问做了优化,作为 Hadoop 生态系统的一部分,它依赖 Hadoop 其他组件提供的重要功能,如 DataNode 数据冗余和 MapReduce 批注处理。

2.hbase特征:

存储在hdfs上;

基于列存储的分布式数据库;

实时大规模的读写数据;

没有真正的索引,行顺序索引,无索引膨胀问题;

自动分区,表增长时,自动分区到新的节点;

线性拓展和区域会自动平衡,运行RegionServer,达到负载均衡的目的;

3.hbase使用场景:

写密集型应用,每天写入量巨大,而相对读数量较小的应用,比如IM的历史消息,游戏的日志等等

不需要复杂查询条件来查询数据的应用,HBase只支持基于rowkey的查询,对于HBase来说,单条记录或者小范围的查询是可以接受的,大范围的查询由于分布式的原因,可能在性能上有点影响,而对于像SQL的join等查询,HBase无法支持。

对性能和可靠性要求非常高的应用,由于HBase本身没有单点故障,可用性非常高

数据量较大,而且增长量无法预估的应用,HBase支持在线扩展,即使在一段时间内数据量呈井喷式增长,也可以通过HBase横向扩展来满足功能。

4.hbase与关系型数据库

拓展困难;

维护复杂;

hbase可解决伸缩行问题;通过增加节点来获取线性拓展;不支持SQL;

5.hbase概念:

单元格:由行和列的坐标交叉决定,有版本号;版本号默认为自动分配,为 HBase 向单元格插入数据时的时间戳;单元格中的内容为未解释的字 节数组。

行键:表中行的键为字节数组;表中的行根据行的键值(即表的主键)进行排序;排序依据为字节序;所有对表的访问都要通过表的主键(二级索引问题)。

列族(column family):行中的列会被划分成不同的列族;同一列族中成员具有相同的前缀;列族的前缀必须是可打印字符构成的;列族修饰符,即结尾字符,可以为任意字符;在 HBase 中,规定使用冒号来分隔列族和列族修饰符;一个表的列族必须作为表模式定义的一部分预先给出,但是新的列族成员可以随后按需要加入;物理上,所有的列族成员都一起存放在文件系统中;HBase 的调优和存储都在列族这个层次上进行的,所以最好使所有列族成员都有相同的访问模式(access pattern)和大小特征。

区域(region):HBase 自动把表水平划分成区域;每个区域由表中行的子集构成;一开始,一个表只有一个区域,随着表变大,区域的个数也会增加;区域是在 HBase 中分布数据的最小单位;在线的所有区域按次序排列就构成了表的所有内容;

6.hbase设计

基于 Hbase 的系统设计与开发中,需要考虑的因素不同于关系型数据库,Hbase 模式本身很简单,但赋予你更多调整的空间,有一些模式写性能很好,但读取数据时表现不好,或者正好相反,类似传统数据库基于范式的 OR 建模,在实际项目中考虑 Hbase 设计模式是,我们需要从以下几方面内容着手:

1.这个表应该有多少个列簇:列族数量越少越好,即使同时有两个列族,查询的时候总是访问其中一个列族,不会同时访问。-当一个表存在多个列族,当基数差距很大时,如A族有100万行,B族10亿行,A族可能会被分散到很多区域region,导致扫描A的效率降低。-另外,多个列族在flush和compaction时,会造成很多I/O负担。

2.列名应该是什么,尽管列名不必在建表时定义,但是读写数据时是需要的

3.单元应该存放什么数据

4.每个单元存储什么时间版本

5.行健结构是什么,应该包括什么信息

a. 不要将RowKey设计成有序的形式,因为这样容易阻塞并行性,将负载压都在一台机器上(数据热点问题)。

b. 定位一个单元,需要行,列名和时间戳。如果一个单元格的坐标很大,会占用内存,索引用光。所以,解决方法:列族名尽量小,如一个字符a,短属性名,而行键长度可读即可(行键长度对数据访问无太大影响),将数字字符转换为数字字节模式(节省空间)。

c. 倒序时间戳有助于找到找到最近版本值。

d. 行键是在列族范围内有效,不同列族中可以拥有同样的行键。

e. 行键永远不能变

7.hbase补充:

1.hbase拓扑结构:拓扑结构: 类似于HDFS的mast与slave,mapreduce的tasktracker与jobtracker的关系,HBase也有master和RegionServer

2.HBase与ZooKeeper的关系是什么?

HBase必须管理一个ZooKeeper实例,它依赖ZooKeeper,主要目的是,通过ZooKeeper来协调区域内的服务器,它负责目录表、主控机地址等重要信息,若有服务器崩溃,HBase就可以通过ZooKeeper来协调分配。

RegionServer在HBase的配置文件conf/regionservers文件中,而HBase集群的站点配置在conf/hbase-site.xml和conf/hbase-env.sh中配置。HBase尽量遵循了Hadoop的规则。


二:hbase的使用

1.创建表:

create "score_tableName","column_family1","column_family2";

2.插入数据

put "score","xiaoming","column_family1","5"

put "score","xiaoming","column_family2:type","1"

3.查询数据:

get "score","column_family1"

get "score","column_family2","type"

规则:

hbase> get ‘t1′, ‘r1′

hbase> get ‘t1′, ‘r1′, {TIMERANGE => [ts1, ts2]}

hbase> get ‘t1′, ‘r1′, {TIMERANGE => [ts1, ts2]}

hbase> get ‘t1′, ‘r1′, {COLUMN => ‘c1′}

hbase> get ‘t1′, ‘r1′, {COLUMN => ['c1', 'c2', 'c3']}

hbase> get ‘t1′, ‘r1′, {COLUMN => ‘c1′, TIMESTAMP => ts1}

hbase> get ‘t1′, ‘r1′, {COLUMN => ‘c1′, TIMERANGE => [ts1, ts2], VERSIONS => 4}

hbase> get ‘t1′, ‘r1′, {COLUMN => ‘c1′, TIMESTAMP => ts1, VERSIONS => 4}

hbase> get ‘t1′, ‘r1′, ‘c1′

hbase> get ‘t1′, ‘r1′, ‘c1′, ‘c2′

hbase> get ‘t1′, ‘r1′, ['c1', 'c2']

4.扫描数据:

scan "score"

5.删除指定数据:

delete ‘scores','column_family2','type'

delete ‘scores','column_family1'

6.修改表结构:

disable table;

alter table;

7.删除一个列簇

hbase(main):003:0>disable'table1'0row(s)in0.0230secondshbase(main):004:0>alter'table1',{ NAME =>'t2', METHOD =>'delete'}

Updating all regions with the new schema...1/1regions updated.

Done.0row(s)in2.2240secondshbase(main):005:0>enable'table1'0row(s)in1.2990seconds

然后在查看该列是否删除,看通过获得表的描述查看,如下: 只剩下列 ‘t1‘。

hbase(main):006:0> describe 'table1'  

Table table1 is ENABLED

table1

COLUMN FAMILIES DESCRIPTION

{NAME =>'t1', DATA_BLOCK_ENCODING =>'NONE', BLOOMFILTER =>'ROW', REPLICATION_SCOPE =>'0', VERSIONS =>'1', COMPRESSIO

N =>'NONE', MIN_VERSIONS =>'0', TTL =>'FOREVER', KEEP_DELETED_CELLS =>'FALSE', BLOCKSIZE =>'65536', IN_MEMORY =>'fa

lse', BLOCKCACHE =>'true'}1row(s) in0.0290seconds

8.删除一个表:drop , 删除表前,需要先屏蔽该表。

hbase(main):007:0>disable'table1'

0row(s)in2.2910seconds

hbase(main):008:0>drop'table1'

0row(s)in1.3030seconds

9.给 row1 这行 age列,并使用counter实现递增 : incr  

hbase(main):024:0>incr'userinfo','row1','age:id'COUNTER VALUE =1

0row(s)in0.0170seconds

hbase(main):025:0>incr'userinfo','row1','age:id'COUNTER VALUE =2

0row(s)in0.0210secondsh

base(main):026:0>incr'userinfo','row1','age:id'COUNTER VALUE =3

0row(s)in0.1270seconds

10.将整个表清空:truncate

hbase(main):028:0>truncate'userinfo'

Truncating'userinfo'table (it may take awhile):

 - Disabling table... 

- Truncating table...0row(s)in4.3360seconds


hbase(main):029:0>scan'userinfo'ROW                            

 COLUMN+CELL0row(s)in0.3490seconds

三:hbase的javaAPI调用(每个版本有所改动,参照官方api):

1.配置:

// 声明静态配置

private static Configuration conf =null;

static{

conf = HBaseConfiguration.create();

conf.set("hbase.zookeeper.quorum",

"master");

conf.set("hbase.zookeeper.property.clientPort","2181");

}

2.操作:

// 创建数据库表

public static  void  createTable(String tableName, String[] columnFamilys)

throwsException {

// 新建一个数据库管理员

HBaseAdmin hAdmin =newHBaseAdmin(conf);

if(hAdmin.tableExists(tableName)) {

System.out.println("表已经存在");

System.exit(0);

}else{

// 新建一个 scores 表的描述

HTableDescriptor tableDesc =newHTableDescriptor(tableName);

// 在描述里添加列族

for(String columnFamily : columnFamilys) {

tableDesc.addFamily(newHColumnDescriptor(columnFamily));

}

// 根据配置好的描述建表

hAdmin.createTable(tableDesc);

System.out.println("创建表成功");

}

}

// 删除数据库表

publicstaticvoiddeleteTable(String tableName)throwsException {

// 新建一个数据库管理员

HBaseAdmin hAdmin =newHBaseAdmin(conf);

if(hAdmin.tableExists(tableName)) {

// 关闭一个表

hAdmin.disableTable(tableName);

// 删除一个表

hAdmin.deleteTable(tableName);

System.out.println("删除表成功");

}else{

System.out.println("删除的表不存在");

System.exit(0);

}

}

// 添加一条数据

publicstaticvoidaddRow(String tableName, String row,

String columnFamily, String column, String value)throwsException {

HTable table =new HTable(conf, tableName);

Put put =newPut(Bytes.toBytes(row));

// 参数出分别:列族、列、值

put.add(Bytes.toBytes(columnFamily), Bytes.toBytes(column),Bytes.toBytes(value));

table.put(put);

}

// 删除一条数据

publicstaticvoiddelRow(String tableName, String row)throwsException {

HTable table =newHTable(conf, tableName);

Delete del =newDelete(Bytes.toBytes(row));

table.delete(del);

}

// 删除多条数据

publicstaticvoiddelMultiRows(String tableName, String[] rows)

throwsException {

HTable table =newHTable(conf, tableName);

List list =newArrayList();

for(String row : rows) {

Delete del =newDelete(Bytes.toBytes(row));

list.add(del);

}table.delete(list);

}

// get row

publicstaticvoidgetRow(String tableName, String row)throwsException {

HTable table =newHTable(conf, tableName);

Get get =newGet(Bytes.toBytes(row));

Result result = table.get(get);

// 输出结果

for(KeyValue rowKV : result.raw()) {

System.out.print("Row Name: "+newString(rowKV.getRow()) +" ");

System.out.print("Timestamp: "+ rowKV.getTimestamp() +" ");

System.out.print("column Family: "+newString(rowKV.getFamily()) +" ");

System.out.print("Row Name:  "+newString(rowKV.getQualifier()) +" ");

System.out.println("Value: "+newString(rowKV.getValue()) +" ");

}

}

// get all records

publicstaticvoidgetAllRows(String tableName)throwsException {

HTable table =newHTable(conf, tableName);

Scan scan =newScan();

ResultScanner results = table.getScanner(scan);

// 输出结果

for(Result result : results) {

for(KeyValue rowKV : result.raw()) {

System.out.print("Row Name: "+newString(rowKV.getRow()) +" ");

System.out.print("Timestamp: "+ rowKV.getTimestamp() +" ");

System.out.print("column Family: "+newString(rowKV.getFamily()) +" ");

System.out

.print("Row Name:  "+newString(rowKV.getQualifier()) +" ");

System.out.println("Value: "+newString(rowKV.getValue()) +" ");

}

}

}

网友评论

登录后评论
0/500
评论
sunt_dota
+ 关注