HBase学习笔记

一、HBase是什么,为什么要使用HBase?

Hbase简介
  • HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。
  • HBase的目标是存储并处理大型的数据,更具体来说是仅需使用普通的硬件配置,就能够处理由成千上万的行和列所组成的大型数据。
  • HBase是Google Bigtable的开源实现,但是也有很多不同之处。比如:Google Bigtable使用GFS作为其文件存储系统,HBase利用Hadoop HDFS作为其文件存储系统;Google运行MAPREDUCE来处理Bigtable中的海量数据,HBase同样利用Hadoop MapReduce来处理HBase中的海量数据;Google Bigtable利用Chubby作为协同服务,HBase利用Zookeeper作为协同服务。
HBase使用场景及应用
使用场景
  • 写密集型应用,每天写入量巨大,而相对读数量较小的应用
  • 不需要复杂查询条件来查询数据的应用
    1.使用rowkey,单条记录或者小范围的查询性能不错,大范围的查询由于分布式的原因,可能在性能上有点影响。
    2.使用HBase的过滤器的话性能比较差。
  • 不需要关联的场景,HBase为NoSQL无法支持join
  • 可靠性要求高
    1.master支持主备热切。
    2.regionServer宕机,region会分配给在线的机器。
    3.数据持久化在HDFS,默认3份,HDFS保证数据可靠性。
    4.内存的数据若丢失可以通过Wal预写日志恢复。
  • 数据量较大,而且增长量无法预估的应用
    HBase支持在线扩展,即使在一段时间内数据量呈井喷式增长,也可以通过HBase横向 扩展来满足功能。
应用
  • 对象存储系统(Medium Object Storage)
  • OLAP的存储(Kylin、Phoenix)
  • 时序型数据(openTsDB应用)
  • 用户画像系统(动态列)
  • 消息/订单系统
  • feed流系统存储(微博)

二、Hbase数据模型

逻辑视图

物理视图

表(table)
  • HBase用表来组织数据,表名是字符串,由可以在文件系统路径里使用的字符组成。
行(row)
  • 在表里,数据按行存储,行由行键(rowkey)唯一标识。行键没有数据类型,总是视为字节数据byte[]。
列族(column family)
  • 行里的数据按照列族分组,列族也影响到HBase数据的物理存放。因此,他们必须事先定义并且不轻易修改。
  • 表中每行拥有相同列族,尽管行不需要在每个列族里存储数据。
  • 列族名字是字符串,由可以再文件系统路径里使用的字符组成。
列 (column )
  • 列名由列族和列修饰符组成,列族内列可任意扩展
列限定符(column qualifier)
  • 列族里的数据通过列限定符或列来定位。
  • 列限定符不必事先定义,列限定符不必在不同行之前保持一致。就像行键一样,列限定符没有数据类型,总是视为字节数组byte[]。
单元(cell)
  • 行键、列族和列限定符一起确定一个单元,存储在单元里的数据称为单元值(value)。
  • 值也没有数据类型,总是视为字节数组byte[]。
时间版本(version)
  • 单元值有时间版本,时间版本用时间戳标识,是一个long。
  • 没有指定时间版本时,当时时间戳作为操作的基础。
  • HBase保留单元值时间版本的数量基于列族进行配置。默认数量是3个。

三、HBase的特性

大:
  • 一个表可以有上亿行,上百万列。
面向列:
  • 面向列表(簇)的存储和权限控制,列(簇)独立检索。
稀疏:
  • 对于为空(NULL)的列,并不占用存储空间,因此,表可以设计的非常稀疏。
无模式:
  • 每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态增加,同一张表中不同的行可以有截然不同的列。
数据多版本:
  • 每个单元中的数据可以有多个版本,默认情况下,版本号自动分配,版本号就是单元格插入时的时间戳。
数据类型单一:
  • 数据类型单一。
与传统数据库对比:

四、HBase操作

存取数据
Connection connection = ConnectionFactory.createConnection(config);
Table table = connection.getTable(TableName.valueOf("mytable"));

//行键
Put p = new Put(Bytes.toBytes("HBaseTest01"));
//列族 + 列限定符 + value
p.add(Bytes.toBytes("info"), Bytes.toBytes("username"),Bytes.toBytes("Poul"));
p.add(Bytes.toBytes("info"), Bytes.toBytes("age"),Bytes.toBytes(18));
p.add(Bytes.toBytes("info"), Bytes.toBytes("password"),Bytes.toBytes("123456"));
table.put(p);
table.close();
修改数据
Put p = new Put(Bytes.toBytes("HBaseTest01"));
p.add(Bytes.toBytes("info"), Bytes.toBytes("password"),Bytes.toBytes("abc123"));
table.put(p);
table.close();
读数据

####### 返回行中所有列族的所有列:

Get g = new Get(Bytes.toBytes("HBaseTest01"));
Result r = table.get(g);

####### 返回指定列族的所有列:

Get g = new Get(Bytes.toBytes("HBaseTest01"));
g.addColumn(Bytes.toBytes("info"),Bytes.toBytes("password"));
Result r = table.get(g);

####### 返回指定值,从字节转换回字符串:

Get g = new Get(Bytes.toBytes("HBaseTest01"));
g.addFamily(Bytes.toBytes("info"));
byte[] b = r.getValue(Bytes.toBytes("info"),Bytes.toBytes("password"));
String password = Bytes.toString(b);
删除数据

####### 删除行中所有列族的所有列:

Delete d = new Delete(Bytes.toBytes("HBaseTest01"));
table.delete(d);

####### 指定坐标删除行的一部分:

Delete d = new Delete(Bytes.toBytes("HBaseTest01"));
d.deleteColumns(Bytes.toBytes("info"),Bytes.toBytes("password"));
table.delete(d);

注意:deleteColumn是删除某一个列族里的最新时间戳版本。
   deleteColumns是删除某个列族里的所有时间戳版本。

posted @ 2020-02-22 16:38  蓝幸运  阅读(233)  评论(1编辑  收藏  举报