
HBas是Hadoop数据库,是一个分布式,可扩展的大数据存储。
这一章博客不介绍如何搭建Hbase,只介绍API代码的编写
HBase官方网站: https://hbase.apache.org/
HBase中文文档: http://abloz.com/hbase/book.html
为什么要用Hbase?
来看看官方解释:
Apache HBase™ is the Hadoop database, a distributed, scalable, big data store.
Use Apache HBase™ when you need random, realtime read/write access to your Big Data. This project’s goal is the hosting of very large tables – billions of rows X millions of columns – atop clusters of commodity hardware. Apache HBase is an open-source, distributed, versioned, non-relational database modeled after Google’s Bigtable: A Distributed Storage System for Structured Data by Chang et al. Just as Bigtable leverages the distributed data storage provided by the Google File System, Apache HBase provides Bigtable-like capabilities on top of Hadoop and HDFS.
大概意思是:
当你需要对大量数据进行随机,实时读/写的操作时,请使用HBase,该项目致力于非常量大的表-数十亿行&百万列- 它是一个开源,面向列,分布式(包括高并发)的非关系数据库(NoSql),基于Hadoop,并存储在HDFS之上
这代表它能够运行在廉价的PC server上搭建大规模的结构化存储集群,关系型数据库无法满足数据疯狂增长的需求,但HBase可以!
我的开发环境
- Linux-CentOs(VMware10虚拟机 3台)
- win10
- idea 2019.1.1
- jdk1.8
- Maven
基本概念
RowKey:是Byte array,是表中每条记录的“主键”,方便快速查找,Rowkey的设计非常重要,后面在重点讲讲我们在RowKey的设计上遇到过的坑。
Column Family:列族,拥有一个名称(string),包含一个或者多个相关列
Column:属于某一个columnfamily,familyName:columnName,每条记录可动态添加
Version Number:类型为Long,默认值是系统时间戳,可由用户自定义
Value(Cell):Byte array
创建HBase项目
- 创建一个普通的maven项目 - 导入依赖: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- <dependencies>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.apache.hbase</groupId>
 <artifactId>hbase-client</artifactId>
 <version>1.3.1</version>
 </dependency>
 </dependencies>
- 创建类MyBaseAPI,编写代码,注意看注释 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176- package com.ujiuye;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.*;
 import org.apache.hadoop.hbase.client.*;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.junit.Before;
 import org.junit.Test;
 import java.util.ArrayList;
 import java.util.List;
 public class MyHBaseAPI {
 //此方法创建使用HBase的资源配置
 private Configuration conf = null;
 @Before// 获取配置对象
 public void getConfiguration() throws Exception {
 // 通过类提供的方法获取配置对象
 conf = HBaseConfiguration.create();
 conf.set("hbase.zookeeper.quorum", "hadoop101");
 conf.set("hbase.zookeeper.property.clientPort", "2181");
 }
 //判断表是否存在
 @Test
 public void tableExist() throws Exception {
 // 1.拿到连接
 Connection conn = ConnectionFactory.createConnection(conf);
 // 2.通过连接拿到hbase的客户端对象
 HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
 // 3.开始操作
 boolean tableExist = admin.tableExists("user");
 if (tableExist) {
 System.out.println("表存在");
 } else {
 System.out.println("表不存在");
 }
 }
 //创建表
 @Test
 public void createTable() throws Exception {
 // 1.拿到连接
 Connection conn = ConnectionFactory.createConnection(conf);
 // 2.通过连接拿到 hbase 的客户端对象
 HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
 // 3.创建表描述器
 HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("user"));
 // 4.设置列族
 tableDescriptor.addFamily(new HColumnDescriptor("info"));
 // 5.执行 创建表
 admin.createTable(tableDescriptor);
 System.out.println("表创建成功");
 }
 // 删除表
 @Test
 public void deleteTable() throws Exception {
 // 1.拿到连接
 Connection conn = ConnectionFactory.createConnection(conf);
 // 2.通过连接拿到 hbase 的客户端对象
 HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
 // 3,禁用表
 admin.disableTable("user");
 // 4.删除表
 admin.deleteTable("user");
 System.out.println("表删除成功");
 }
 //向表中插入数据
 @Test
 public void insertData() throws Exception {
 // 1.拿到连接
 Connection conn = ConnectionFactory.createConnection(conf);
 // 2.通过连接拿到 hbase 的客户端对象
 HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
 Table table = conn.getTable(TableName.valueOf("user"));
 // 3. 封装数据,注意要用hbase提供的工具来转化为字节数组,不要用字符串的getBytes方法
 Put put = new Put(Bytes.toBytes("1001"));
 // 4.设置 列族 类名 值
 put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("zhangsan"));
 // 5. 向表中插入数据
 table.put(put);
 }
 //批量插入数据
 @Test
 public void insertDatas() throws Exception {
 // 拿到连接
 Connection conn = ConnectionFactory.createConnection(conf);
 // 获取表
 Table table = conn.getTable(TableName.valueOf("user"));
 // 批量插入数据
 Put put = new Put(Bytes.toBytes("1001"));
 // 设置 列族 类名 值
 put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("zhangsan"));
 Put put2 = new Put(Bytes.toBytes("1002"));
 // 设置 列族 类名 值
 put2.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("wangwu"));
 List<Put> list = new ArrayList<Put>();
 list.add(put);
 list.add(put2);
 table.put(list);
 // 关闭
 table.close();
 }
 // 删除一行数据 / 多行数据
 @Test
 public void deleteData() throws Exception {
 // 1.拿到连接
 Connection conn = ConnectionFactory.createConnection(conf);
 // 2.通过连接拿到 hbase 的客户端对象
 // HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
 Table table = conn.getTable(TableName.valueOf("user"));
 // Delete delete = new Delete(Bytes.toBytes("1002"));
 // table.delete(delete);
 // 批量删除
 Delete delete = new Delete(Bytes.toBytes("1001"));
 Delete delete1 = new Delete(Bytes.toBytes("1002"));
 List<Delete> list = new ArrayList<Delete>();
 list.add(delete);
 list.add(delete1);
 table.delete(list);
 }
 // 获取所有数据
 @Test
 public void getAllData() throws Exception {
 // 1.拿到连接
 Connection conn = ConnectionFactory.createConnection(conf);
 // 2.获取表
 Table table = conn.getTable(TableName.valueOf("user"));
 // 3.构造一个 scan 对象
 Scan scan = new Scan(Bytes.toBytes(""));
 ResultScanner scanner = table.getScanner(scan);
 for (Result result : scanner) {
 Cell[] rawCells = result.rawCells();// 获取某一行数据
 for (Cell cell : rawCells) {
 String row = Bytes.toString(CellUtil.cloneRow(cell));
 String cf = Bytes.toString(CellUtil.cloneFamily(cell));
 String cl = Bytes.toString(CellUtil.cloneQualifier(cell));
 String va = Bytes.toString(CellUtil.cloneValue(cell));
 System.out.println(row+"---"+cf+"---"+cl+"---"+va);
 }
 }
 }
 // 获取某一行数据,指定列族,列
 @Test
 public void getSomeData() throws Exception{
 // 1.拿到连接 和 表
 Connection conn = ConnectionFactory.createConnection(conf);
 Table table = conn.getTable(TableName.valueOf("user"));
 Get get = new Get(Bytes.toBytes("1001"));
 Result result = table.get(get);
 Cell[] rawCells = result.rawCells();//获取某一行的所有数据
 for (Cell cell : rawCells) {
 String row = Bytes.toString(CellUtil.cloneRow(cell));
 String cf = Bytes.toString(CellUtil.cloneFamily(cell));
 String cl = Bytes.toString(CellUtil.cloneQualifier(cell));
 String va = Bytes.toString(CellUtil.cloneValue(cell));
 System.out.println(row+"---"+cf+"---"+cl+"---"+va);
 }
 }
 }
HBase Shell简单验证操作
说几个HBase Shell的基本操作,不然都不知道怎么验证上面的代码
- 首先启动HBase
[root@hadoop101 hbase] $ bin/start-hbase.sh
然后进入HBase Shell命令行操作
- 在Shell操作的时候如果需要后退直接按 Backspace 是不行的,必须Ctrl+Backspace
[root@hadoop101 hbase]$ bin/hbase shell
- 查看当前数据库有哪些表
hbase(main):002:0> list
- 查询表数据 scan+’表名’ STARTROW是开始行 到 STOPROW结束行,无STOPROW的话是到最后
hbase(main):008:0> scan ‘student’
hbase(main):009:0> scan ‘student’,{STARTROW => ‘1001’, STOPROW => ‘1002’}
hbase(main):010:0> scan ‘student’,{STARTROW => ‘1001’}
验证代码一个 scan 就够了,
内存优化
HBase操作过程中需要大量的内存开销,毕竟Table是可以缓存在内存中的,一般会分配整个可用内存的70%给HBase的Java堆。但是不建议分配非常大的堆内存,因为GC过程持续太久会导致RegionServer处于长期不可用状态,一般16~48G内存就可以了,如果因为框架占用内存过高导致系统内存不足,框架一样会被系统服务拖死。
HBase在商业项目中的能力
每天:
- 消息量:发送和接收的消息数超过60亿 
- 将近1000亿条数据的读写 
- 高峰期每秒150万左右操作 
- 整体读取数据占有约55%,写入占有45% 
- 超过2PB的数据,涉及冗余共6PB数据 
- 数据每月大概增长300千兆字节。 
我只是拿我自己的博客当一个笔记而已,如有类似,纯属雷同

