一: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()) +" ");
}
}
}