HBase介绍及使用
1、介绍
hbase是bigtable的开源java版本。是建立在hdfs之上,提供高可靠性、高性能、列存储、可伸缩、实时读写nosql的数据库系统。
2、与RDBMS的区别
1. RDBMS
结构:
- 数据库以表的形式存在
- 支持FAT、NTFS、EXT、文件系统
- 使用Commit log存储日志
- 参考系统是坐标系统
- 使用主键(PK)
- 支持分区
- 使用行、列、单元格
功能: - 支持向上扩展
- 使用SQL查询
- 面向行,即每一行都是一个连续单元
- 数据总量依赖于服务器配置
- 具有ACID支持
- 适合结构化数据
- 传统关系型数据库一般都是中心化的
- 支持事务
- 支持Join
2. HBase
结构:
- 数据库以region的形式存在
- 支持HDFS文件系统
- 使用WAL(Write-Ahead Logs)存储日志
- 参考系统是Zookeeper
- 使用行键(row key)
- 支持分片
- 使用行、列、列族和单元格
功能: - 支持向外扩展
- 使用API和MapReduce来访问HBase表数据
- 面向列,即每一列都是一个连续的单元
- 数据总量不依赖具体某台机器,而取决于机器数量
- HBase不支持ACID(Atomicity、Consistency、Isolation、Durability)
- 适合结构化数据和非结构化数据
- 一般都是分布式的
- HBase不支持事务
- 不支持Join
3、基础架构
HMaster
功能:
- 监控RegionServer
- 处理RegionServer故障转移
- 处理元数据的变更
- 处理region的分配或移除
- 在空闲时间进行数据的负载均衡
- 通过Zookeeper发布自己的位置给客户端
RegionServer
功能: - 负责存储HBase的实际数据
- 处理分配给它的Region
- 刷新缓存到HDFS
- 维护HLog
- 执行压缩
- 负责处理Region分片
组件:
- Write-Ahead logs
HBase的修改记录,当对HBase读写数据的时候,数据不是直接写进磁盘,它会在内存中保留一段时间(时间以及数据量阈值可以设定)。但把数据保存在内存中可能有更高的概率引起数据丢失,为了解决这个问题,数据会先写在一个叫做Write-Ahead logfile的文件中,然后再写入内存中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。 - HFile
这是在磁盘上保存原始数据的实际的物理文件,是实际的存储文件。 - Store
HFile存储在Store中,一个Store对应HBase表中的一个列族。 - MemStore
顾名思义,就是内存存储,位于内存中,用来保存当前的数据操作,所以当数据保存在WAL中之后,RegsionServer会在内存中存储键值对。 - Region
Hbase表的分片,HBase表会根据RowKey值被切分成不同的region存储在RegionServer中,在一个RegionServer中可以有多个不同的region。
4、常用Shell
- 进入客户端命令:hbase shell
- 查看帮助命令:help
- 查看当前数据库中有哪些表:list
- 创建一张表:
create 'user', 'info', 'data'
create 'user', {NAME => 'info', VERSIONS => '3'},{NAME => 'data'}
- 添加数据操作:
put 'user', 'rk0001', 'info:name', 'zhangsan'
- 查询数据操作:
get 'user', 'rk0001'
- 查询所有数据:scan ‘user’
- 列族查询:scan ‘user’, {COLUMNS => ‘info’}
- 更新数据:与插入操作相同
- 删除数据:
delete 'user', 'rk0001', 'info:name'
- 清空表数据:truncate ‘user’
- 删除表:先禁用,在删除
disable 'user'
drop 'user'
- 统计一张表有多少数据 :count ‘user’
5、Java API
创建表
@Test
public void createTable() throws IOException {
//创建配置文件对象,并指定zookeeper的连接地址
Configuration configuration = HBaseConfiguration.create();
configuration.set("hbase.zookeeper.property.clientPort", "2181");
configuration.set("hbase.zookeeper.quorum", "node01,node02,node03");
//集群配置↓
//configuration.set("hbase.zookeeper.quorum", "101.236.39.141,101.236.46.114,101.236.46.113");
configuration.set("hbase.master", "node01:60000");
Connection connection = ConnectionFactory.createConnection(configuration);
Admin admin = connection.getAdmin();
//通过HTableDescriptor来实现我们表的参数设置,包括表名,列族等等
HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("myuser"));
//添加列族
hTableDescriptor.addFamily(new HColumnDescriptor("f1"));
//添加列族
hTableDescriptor.addFamily(new HColumnDescriptor("f2"));
//创建表
boolean myuser = admin.tableExists(TableName.valueOf("myuser"));
if(!myuser){
admin.createTable(hTableDescriptor);
}
//关闭客户端连接
admin.close();
}
向表中添加数据
@Test
public void addDatas() throws IOException {
//获取连接
Configuration configuration = HBaseConfiguration.create();
configuration.set("hbase.zookeeper.quorum", "node01:2181,node02:2181");
Connection connection = ConnectionFactory.createConnection(configuration);
//获取表
Table myuser = connection.getTable(TableName.valueOf("myuser"));
//创建put对象,并指定rowkey
Put put = new Put("0001".getBytes());
put.addColumn("f1".getBytes(),"id".getBytes(), Bytes.toBytes(1));
put.addColumn("f1".getBytes(),"name".getBytes(), Bytes.toBytes("张三"));
put.addColumn("f1".getBytes(),"age".getBytes(), Bytes.toBytes(18));
put.addColumn("f2".getBytes(),"address".getBytes(), Bytes.toBytes("地球人"));
put.addColumn("f2".getBytes(),"phone".getBytes(), Bytes.toBytes("15874102589"));
//插入数据
myuser.put(put);
//关闭表
myuser.close();
}
查询数据
@Test
public void searchData() throws IOException {
Configuration configuration = HBaseConfiguration.create();
configuration.set("hbase.zookeeper.quorum","node01:2181,node02:2181,node03:2181");
Connection connection = ConnectionFactory.createConnection(configuration);
Table myuser = connection.getTable(TableName.valueOf("myuser"));
Get get = new Get(Bytes.toBytes("0003"));
Result result = myuser.get(get);
Cell[] cells = result.rawCells();
//获取所有的列名称以及列的值
for (Cell cell : cells) {
//注意,如果列属性是int类型,那么这里就不会显示
System.out.println(Bytes.toString(cell.getQualifierArray(),cell.getQualifierOffset(),cell.getQualifierLength()));
System.out.println(Bytes.toString(cell.getValueArray(),cell.getValueOffset(),cell.getValueLength()));
}
myuser.close();
}
过滤器查询
比较过滤器:
- rowKey过滤器RowFilter
- 列簇过滤器 FamilyFilter
- 列过滤器 QualiFilter
- 列值过滤器 ValueFilter
专用过滤器: - 单列值过滤器 SingleColumnValueFilter
- 列值排除过滤器 SingleColumnValueExcludeFilter
- rowkey前缀过滤器PrefixFilter
- 分页过滤器 PageFilter
多过滤器综合查询 FilterList
根据rowkey删除数据
@Test
public void deleteByRowKey() throws IOException {
//获取连接
Configuration configuration = HBaseConfiguration.create();
configuration.set("hbase.zookeeper.quorum","node01:2181,node02:2181,node03:2181");
Connection connection = ConnectionFactory.createConnection(configuration);
Table myuser = connection.getTable(TableName.valueOf("myuser"));
Delete delete = new Delete("0001".getBytes());
myuser.delete(delete);
myuser.close();
}
删除表
@Test
public void deleteTable() throws IOException {
//获取连接
Configuration configuration = HBaseConfiguration.create();
configuration.set("hbase.zookeeper.quorum","node01:2181,node02:2181,node03:2181");
Connection connection = ConnectionFactory.createConnection(configuration);
Admin admin = connection.getAdmin();
admin.disableTable(TableName.valueOf("myuser"));
admin.deleteTable(TableName.valueOf("myuser"));
admin.close();
}