项目实训第十二天
本文最后更新于:2021年7月23日 晚上
HBase
基本操作
注意问题
- HBase作为一个数据库,提供了基本的增删改查的能力,但是HBase基于HDFS来进行数据的存储,在HDFS“允许一次写入,多次读取,不允许修改,但是允许追加”的前提下,HBase是怎么实现改操作的?当在HBase中,对数据进行修改的时候,实际上并不是真正去改变HDFS中的数据而是在HDFS的文件后边来追加一条数据,当用户需要获取数据的时候,会从文件中来返回最新的数据,那么此时从用户角度就是将数据进行了修改 - HBase在每条数据之后都会追加一个时间戳用于标记数据的新旧问题,这个时间戳称之为数据的版本(VERSION)
- 在HBase中,需要通过行键+列族+列+时间戳/版本可以锁定唯一的一条数据,这种结构称之为是一个Cell(单元)
- 在HBase中,当表建好之后,这个表的版本数就不能改变了。默认情况下,如果不指定,每一个表只会保留1个版本的数据,同时需要注意,也只允许对外获取1个版本的数据 - 如果需要获取多个版本的数据,那么此时需要在建表的时候指定保留版本数,以及对外获取的时候需要指定获取的版本数量
- 在HBase中,删除表之前需要先禁用这个表
- 在HBase中,没有database的概念,取而代之的是namespace(名称空间),可以将表放到不同的名称空间下
- 在HBase启动的时候,会自带了两个namespace:default和hbase。在建表的时候如果不指定,那么表默认是放在default空间下的;hbase空间下放的是HBase本身的元数据
基本命令
命令 | 解释 |
---|---|
disable ‘person’ | 禁用表 |
drop ‘person’ | 删除表 |
create ‘person’, {NAME => ‘basic’, VERSIONS => 4}, {NAME => ‘info’, VERSIONS => 5} | 建立person表,包含2个列族,这2个列族各自保留对应版本数的数据 |
get ‘person’, ‘p1’, {COLUMN => ‘basic:age’, VERSIONS => 4} | 获取指定列的多个版本的数据 |
scan ‘person’, {COLUMNS => ‘basic’, VERSIONS => 4} | 获取指定列族的多版本数据 |
create_namespace ‘demo’ | 创建名称空间 |
list_namespace | 查看所有的名称空间 |
list_namespace_tables ‘default’ | 查看指定空间下的表 |
create ‘demo:person’, {NAME => ‘basic’, VERSIONS => 5}, {NAME => ‘other’, VERSIONS => 3} | 在指定空间下建表 |
put ‘demo:person’, ‘p1’, ‘basic:name’, ‘tom’ | 向指定空间指定表中来添加数据 |
disable ‘demo:person’ | 禁用指定空间下的指定表 |
drop ‘demo:person’ | 删除指定空间下的指定表 |
drop_namespace ‘demo’ | 删除指定空间,要求这个空间为空 |
count ‘person’ | 统计这个表中的行键个数 |
get_splits ‘person’ | 获取指定表中的HRegion的个数 |
truncate ‘person’ | 摧毁重建表 |
alter ‘person’, {NAME => ‘basic’, VERSIONS => 5} | 修改指定表的属性 |
describe ‘person’ 或者 desc ‘person’ |
描述表信息 |
exists ‘person’ | 判断表是否存在 |
is_disabled ‘person’ | 判断表是否被禁用 |
is_enabled ‘person’ | 判断表是否被启用 |
list_regions ‘person’ | 列出指定表中的HRegion的信息 |
show_filters | 列出所有的过滤器 |
list | 获取所有空间下的所有的表 |
disable_all ‘demo:.*’ | 禁用指定空间下的所有的表,在使用的时候需要给定正则表达式 |
drop_all ‘demo:.*’ | 删除指定空间下的所有的表 |
API操作
Namespache操作
发起连接
1
2
3
4
5
6
7
8
9
10
11
12
13@Before
public void connect() throws IOException {
// 获取HBase的配置信息
Configuration conf = HBaseConfiguration.create();
// 指定Zookeeper的连接地址
conf.set("hbase.zookeeper.quorum", "hadoop:2181,hadoop02:2181,hadoop03:2181");
// 获取连接
connection = ConnectionFactory.createConnection(conf);
// 获取管理权
admin = connection.getAdmin();
}创建名称空间
1
2
3
4
5
6
7@Test
public void createNamespace() throws IOException {
// 构建一个NamespaceDescriptor - 空间描述器
NamespaceDescriptor descriptor = NamespaceDescriptor.create("demo").build();
// 创建名称空间
admin.createNamespace(descriptor);
}查看所有的名称空间
1
2
3
4
5
6
7
8
9@Test
public void listNamespaces() throws IOException {
// 获取所有的名称空间
String[] namespaces = admin.listNamespaces();
// 遍历数组
for (String namespace : namespaces) {
System.out.println(namespace);
}
}删除名称空间
1
2
3
4@Test
public void dropNamespace() throws IOException {
admin.deleteNamespace("demo");
}关闭连接
1
2
3
4
5
6
7@After
public void close() throws IOException {
// 关闭管理权
admin.close();
// 关闭连接
connection.close();
}
Table操作
发起连接
1
2
3
4
5
6
7
8
9
10
11
12
13@Before
public void connect() throws IOException {
// 获取HBase的配置
Configuration conf = HBaseConfiguration.create();
// 设置Zookeeper的连接地址
conf.set("hbase.zookeeper.quorum", "hadoop:2181,hadoop02:2181,hadoop03:2181");
// 获取连接
connection = ConnectionFactory.createConnection(conf);
// 获取管理权
admin = connection.getAdmin();
// 指定表
users = connection.getTable(TableName.valueOf("users"));
}建表
1
2
3
4
5
6
7
8
9
10
11
12
13
14@Test
public void createTable() throws IOException {
// 构建列族描述器
ColumnFamilyDescriptor cf1 = ColumnFamilyDescriptorBuilder
.newBuilder("basic".getBytes(StandardCharsets.UTF_8)).build();
ColumnFamilyDescriptor cf2 = ColumnFamilyDescriptorBuilder
.newBuilder("info".getBytes(StandardCharsets.UTF_8)).build();
// 构建TableDescriptor - 表描述器
TableDescriptor table = TableDescriptorBuilder
.newBuilder(TableName.valueOf("users"))
.setColumnFamily(cf1).setColumnFamily(cf2).build();
// 建表
admin.createTable(table);
}添加/追加数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16@Test
public void appendData() throws IOException {
// 构建Append对象
Append append = new Append("u1".getBytes(StandardCharsets.UTF_8));
// 添加数据
byte[] basic = "basic".getBytes(StandardCharsets.UTF_8);
byte[] info = "info".getBytes(StandardCharsets.UTF_8);
append.addColumn(basic, "name".getBytes(StandardCharsets.UTF_8), "David".getBytes(StandardCharsets.UTF_8));
append.addColumn(basic, "age".getBytes(StandardCharsets.UTF_8), "19".getBytes(StandardCharsets.UTF_8));
append.addColumn(basic, "gender".getBytes(StandardCharsets.UTF_8), "male".getBytes(StandardCharsets.UTF_8));
append.addColumn(info, "height".getBytes(StandardCharsets.UTF_8), "185.5".getBytes(StandardCharsets.UTF_8));
append.addColumn(info, "weight".getBytes(StandardCharsets.UTF_8), "70.5".getBytes(StandardCharsets.UTF_8));
append.addColumn(info,"address".getBytes(StandardCharsets.UTF_8), "chongqing".getBytes(StandardCharsets.UTF_8));
// 追加
users.append(append);
}添加/修改数据
1
2
3
4
5
6
7
8
9
10
11@Test
public void putData() throws IOException {
// 封装Put对象
Put put = new Put("u2".getBytes(StandardCharsets.UTF_8));
// 指定数据
put.addColumn("basic".getBytes(StandardCharsets.UTF_8),
"name".getBytes(StandardCharsets.UTF_8),
"Evan".getBytes(StandardCharsets.UTF_8));
// 修改/添加数据
users.put(put);
}测试:添加百万条数据
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@Test
public void putMillionData() throws IOException {
// 记录起始时间
long begin = System.currentTimeMillis();
// 构建集合,实现批量添加
List<Put> list = new ArrayList<>();
// 指定列族和列
byte[] basic = "basic".getBytes(StandardCharsets.UTF_8);
byte[] password = "password".getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < 1000000; i++) {
// 构建Put对象
Put put = new Put(("u" + i).getBytes(StandardCharsets.UTF_8));
// 添加数据
put.addColumn(basic, password, getPassword());
// 将数据放入集合
list.add(put);
// 每1000条数据写出一次
if (list.size() >= 1000) {
users.put(list);
// 清空集合
list.clear();
}
}
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println(end - begin);
}
// 产生初始密码
private byte[] getPassword() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 6; i++) {
char c = (char) (Math.random() * 26 + 65);
sb.append(c);
}
return sb.toString().getBytes(StandardCharsets.UTF_8);
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!