文章目录
分布式NoSQL列存储数据库Hbase(二)
知识点01:课程回顾
知识点02:课程目标
知识点03:Hbase使用场景
知识点04:Hbase运行命令脚本文件
知识点05:DDL命令:NS的管理
0、命令行的使用
1、列举所有的NS
2、列举NS中的所有表
3、创建NS
4、删除NS
知识点11:DML命令:incr
知识点12:DML命令:count
知识点13:JavaAPI:构建工程依赖
知识点14:JavaAPI:构建连接
知识点15:JavaAPI:DDL
作业
附录一:Hbase Maven依赖
附录一:Hbase Maven依赖
分布式NoSQL列存储数据库Hbase(二)
知识点01:课程回顾
Hbase的介绍
功能:分布式NoSQL列存储数据库,用于实现大数据高性能的实时随机的数据存储
应用场景:所有实时数据存储的场景
特点
分布式内存 + 分布式磁盘:大数据存储
基于内存的列存储:高性能数据的存储
MySQL:只能满足小数据量的存储
HDFS:纯离线的文件系统
Hbase虽然基于HDFS,但是整体是一个实时的技术
Hbase上层是分布式内存,底层才是HDFS
Hbase将数据存储在HDFS上,也做了性能优化
Hive:Hive本质还是HDFS,只是对HDFS封装了表的结构接口
Hive功能:构建离线数据仓库:直接使用HDFS存储
Hbase功能:用于解决实时数据存储:内存+优化HDFS存储
设计思想:怎么实现?
大数据:分布式的设计
高性能:基于内存
核心:冷热数据分离
刚产生的数据,被读的概率最大,称为热数据,将热数据写入分布式内存
产生很久的数据,被读的概率比较小,就是冷数据,将冷数据存储在磁盘中【HDFS】
Hbase的设计概念
数据库:Namespace
表:Table
任何一张表,都属于某个NS
在访问表时,除了default的Namespace中的表,其他所有Namespace的表在使用时,必须加上NS名称nsName:tbName
表:分布式表
任何一张表都可以划分为多个分区,每个分区存储在不同的机器上
Region:表的分区,存储在RegionServer
行:Rowkey
行健:每张表都自带行健这一列,这一列的值由我们自己定义
唯一标记一行
作为唯一索引:Hbase中不支持创建索引,默认只有rowkey作为唯一索引
列:column family : column,唯一标识一列
column family :列族,对列的分组,将所有列划分不同的组中,为了提高性能
假设100列,如果不分组,查询时,最多比较100列才能找到我要的列
假设100列,如果分组了,每组50列,查询时,告诉你在第一列,最多比较51次
column:每一列都属于某一个列族,相同列族中列会存储在一起
支持多版本:一列中可以存储多个版本的值,通过时间戳来区分,列族级别的属性
Hbase架构组成
架构中角色
Hbase:主从架构
HMaster:管理节点
HRegionServer:存储结构,用于构建分布式内存
HDFS:分布式磁盘
Zookeeper:存储元数据、辅助选举
集群搭建【搭建成功即可】
知识点02:课程目标
工作使用Hbase几种场景
集群管理【偏运维管理】
测试开发【熟悉命令】
生产开发【代码开发】
测试开发命令【熟练的记住命令语法】
类似于SQL的学习
DDL:数据库、表的管理命令
DML:数据增删改查
生产开发API【重点:必须熟练掌握API】
类似于JDBC代码的开发
JavaAPI:MR或者Spark来读取数据,进行计算
知识点03:Hbase使用场景
1、集群管理
应用场景:运维做运维集群管理,我们开发用的不多
需求:封装Hbase集群管理命令脚本
类似于hive -f xxx.sql
举个栗子:每天Hbase集群能定时的自动创建一张表
分析
实现:通过Hbase的客户端运行命令文件,通过调度工具进行调度实现定时运行
用法:hbase shell 文件路径
注意:所有的Hbase命令文件,最后一行命令必须为exit
2、测试开发
需求:一般用于测试开发,执行DDL操作,类似于SQL之类的命令
实现:Hbase shell命令行
用法:hbase shell
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x49RUcC1-1616631212947)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317090127608.png)]
3、生产开发
需求:一般用于生产开发,通过MapReduce或者Spark等程序读写Hbase,类似于JDBC
举个栗子:读取Hbase中的数据,进行分析处理,统计UV、PV
分析
step1:通过分布式计算程序Spark、Flink读取Hbase数据
step2:对读取到的数据进行统计分析
step3:保存结果
实现:分布式计算程序通过Java API读写Hbase,实现数据处理
用法:在MapReduce或者Spark中集成API
知识点04:Hbase运行命令脚本文件
知识点05:DDL命令:NS的管理
0、命令行的使用
启动hbase shell
查看帮助help
DDL:数据库命令Group name: namespace
Commands: alter_namespace, create_namespace, describe_namespace, drop_namespace, list_namespace, list_namespace_tables
DDL:表命令Group name: ddl
Commands: alter, alter_async, alter_status, clone_table_schema, create, describe, disable, disable_all, drop, drop_all, enable, enable_all, exists, get_table, is_disabled, is_enabled, list, list_regions, locate_region, show_filters
DML:数据操作命令Group name: dml
Commands: append, count, delete, deleteall, get, get_counter, get_splits, incr, put, scan, truncate, truncate_preserve
工具命令Group name: tools
Commands: assign, balance_switch, balancer, balancer_enabled, catalogjanitor_enabled, catalogjanitor_run, catalogjanitor_switch, cleaner_chore_enabled, cleaner_chore_run, cleaner_chore_switch, clear_block_cache, clear_compaction_queues, clear_deadservers, close_region, compact, compact_rs, compaction_state, flush, is_in_maintenance_mode, list_deadservers, major_compact, merge_region, move, normalize, normalizer_enabled, normalizer_switch, split, splitormerge_enabled, splitormerge_switch, stop_master, stop_regionserver, trace, unassign, wal_roll, zk_dump
查看命令的用法help '命令'
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dMC2s2IY-1616631212953)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317091952518.png)]
退出exit
1、列举所有的NS
命令:list_namespace
语法list_namespace
示例list_namespace
2、列举NS中的所有表
3、创建NS
4、删除NS
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lb2DJag6-1616631212957)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317092707405.png)]
## 知识点06:DDL命令:Table的管理
### 1、列举表
- 命令:list
- SQL:show tables
- 语法
list- 示例
list[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vY0wVLUR-1616631212957)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317093026595.png)]
### 2、创建表
- 命令:create
- SQL:表名 + 列的信息【名称和类型】
```
create table tbname(
col1 type1 ,
……
colN typeN
);
```
- ==Hbase:必须指定表名 + 至少一个列族==
- 语法
```shell
//表示在ns1的namespace中创建一张表t1,这张表有一个列族叫f1,这个列族中的所有列可以存储5个版本的值
create 'ns1:t1', {NAME => 'f1', VERSIONS => 5}
//在default的namespace中创建一张表t1,这张表有三个列族,f1,f2,f3,每个列族的属性都是默认的
create 't1', 'f1', 'f2', 'f3'
create ‘itcast:t2’,‘cf1’,‘cf3’ = create ‘t1’,{NAME=>‘cf1’},{NAME=>‘cf2’},{NAME=>‘cf3’}[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cb0r3P0R-1616631212958)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317093534080.png)]
### 3、查看表
- 命令:desc
- SQL :desc tbname
- 语法
desc ‘表名’- 示例
desc ‘t1’
hbase(main):022:0> desc ‘t1’
Table t1 is ENABLED
t1
COLUMN FAMILIES DESCRIPTION
{NAME => ‘cf1’, VERSIONS => ‘1’, EVICT_BLOCKS_ON_CLOSE => ‘false’, NEW_VERSION_BEHAVIOR => ‘false’, KEEP_DELETED_CELLS => ‘FALSE’, CACHE_DATA_ON_WRITE => ‘false’, DATA_BLOCK_ENCODING => ‘NONE’, TTL => ‘FOREVER’, MIN_VERSIONS => ‘0’, REPLICATION_SCOPE => ‘0’, BLOOMFILTER => ‘ROW’, CACHE_INDEX_ON_WRITE => ‘false’, IN_MEMORY => ‘false’, CACHE_BLOOMS_ON_WRITE => ‘false’, PREFETCH_BLOCKS_ON_OPEN => ‘false’, COMPRESSION => ‘NONE’, BLOCKCACHE => ‘true’, BLOCKSIZE => ‘65536’}
{NAME => ‘cf2’, VERSIONS => ‘3’, EVICT_BLOCKS_ON_CLOSE => ‘false’, NEW_VERSION_BEHAVIOR => ‘false’, KEEP_DELETED_CELLS => ‘FALSE’, CACHE_DATA_ON_WRITE => ‘false’, DATA_BLOCK_ENCODING => ‘NONE’, TTL => ‘FOREVER’, MIN_VERSIONS => ‘0’, REPLICATION_SCOPE => ‘0’, BLOOMFILTER => ‘ROW’, CACHE_INDEX_ON_WRITE => ‘false’, IN_MEMORY => ‘false’, CACHE_BLOOMS_ON_WRITE => ‘false’, PREFETCH_BLOCKS_ON_OPEN => ‘false’, COMPRESSION => ‘NONE’, BLOCKCACHE => ‘true’, BLOCKSIZE => ‘65536’}### 4、删除表
- 命令:drop
- SQL:drop table tbname
- 语法
drop ‘表名’- 示例
drop ‘t1’- 注意:如果要对表进行删除,必须先禁用表,再删除表
### 5、禁用/启用表
- 命令:disable / enable
- 功能
- Hbase为了避免修改或者删除表,这张表正在对外提供读写服务
- 规则:修改或者删除表时,必须先禁用表,表示这张表暂时不能对外提供服务
- 如果是删除:禁用以后删除
- 如果是修改:先禁用,然后修改,修改完成以后启用
- 语法
disable ‘表名’
enable ‘表名’- 示例
disable ‘t1’
enable ‘t1’[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BlFKjMrn-1616631212959)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317094412194.png)]
### 6、判断表是否存在
- 命令:exists
- 语法
exists ‘表名’- 示例
exists ‘t1’[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GjWh74jG-1616631212959)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317094559510.png)]
## 知识点07:DML命令:put
- ==功能==:插入 / 更新数据【某一行的某一列】
- SQL
- insert:用于插入一条新的数据
- update:用于更新一条数据
- replace:插入更新命令,如果不存在就插入,如果存在就更新
- 原理:先做判断,如果不存在,就直接插入,如果存在,就删除再插入
- Hbase:put
- 等同于replace
- ==语法==
put NS名称:表的名称,‘Rowkey’,‘列族:列’,‘值’
put ‘ns1:t1’, ‘r1’, ‘cf:c1’, ‘value’- 示例
put ‘itcast:t2’,‘20210201_001’,‘cf1:name’,‘laoda’
put ‘itcast:t2’,‘20210201_001’,‘cf1:age’,18
put ‘itcast:t2’,‘20210201_001’,‘cf3:phone’,‘110’
put ‘itcast:t2’,‘20210201_001’,‘cf3:addr’,‘shanghai’
put ‘itcast:t2’,‘20210101_000’,‘cf1:name’,‘laoer’
put ‘itcast:t2’,‘20210101_000’,‘cf3:addr’,‘bejing’- ==注意==
- put:如果不存在,就插入,如果存在就更新
```
put 'itcast:t2','20210101_000','cf1:name','laosan'
```
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KEM3poHf-1616631212960)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317100911065.png)]
- 写入的数据按照Rowkey进行了排序:按照Rowkey的字典顺序进行排序
- 每个rowkey内部按照列做了排序
- ==Hbase中的更新是假的,伪更新==
- 只是让用户看起来更新了,但实际没有更新
- 实现更新数据时,插入了一条新的数据,老的数据被标记为更新不显示,没有被真正删除
- 只显示最新的数据,不显示老的数据
- ==为什么要这么做?为什么不直接对数据进行修改,而是插入一条新的数据来代替更新操作==
- ==保证性能==
- 观察结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tBj5ddiF-1616631212961)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317100609728.png)]
## 知识点08:DML命令:get
- ==功能==:读取某个Rowkey的数据
- 注意:==缺点:get命令最多只能返回一个rowkey的数据==,根据Rowkey进行检索数据
- Rowkey作为Hbase的唯一索引,按照rowkey是走索引的
- ==优点:Get是Hbase中查询数据最快的方式==
- 语法
get 表名 rowkey [列族,列]
get ‘ns:tbname’,‘rowkey’
get ‘ns:tbname’,‘rowkey’,[cf]
get ‘ns:tbname’,‘rowkey’,[cf] | [cf:col]- 示例
get ‘ORDER_INFO’,‘f8f3ca6f-2f5c-44fd-9755-1792de183845’
get ‘ORDER_INFO’,‘f8f3ca6f-2f5c-44fd-9755-1792de183845’,‘C1’
get ‘ORDER_INFO’,‘f8f3ca6f-2f5c-44fd-9755-1792de183845’,‘C1:USER_ID’[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dq8Aqpz6-1616631212962)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317101906441.png)]
## 知识点09:DML命令:scan
- 功能:根据条件匹配读取多个Rowkey的数据
- 语法
```shell
scan 'tbname'//一般不用
scan 'tbname',{Filter} //用到最多
示例hbase> scan 't1', {ROWPREFIXFILTER => 'row2', FILTER => "
(QualifierFilter (>=, 'binary:xyz')) AND (TimestampsFilter ( 123, 456))"}
hbase> scan 't1', {FILTER =>
org.apache.hadoop.hbase.filter.ColumnPaginationFilter.new(1, 0)}
[/list] scan ‘itcast:t2’
#rowkey前缀过滤器
scan ‘itcast:t2’, {ROWPREFIXFILTER => ‘2021’}
scan ‘itcast:t2’, {ROWPREFIXFILTER => ‘202101’}
#rowkey范围过滤器
#STARTROW:从某个rowkey开始,包含,闭区间
#STOPROW:到某个rowkey结束,不包含,开区间
scan ‘itcast:t2’,{STARTROW=>‘20210101_000’}
scan ‘itcast:t2’,{STARTROW=>‘20210201_001’}
scan ‘itcast:t2’,{STARTROW=>‘20210101_000’,STOPROW=>‘20210201_001’}
scan ‘itcast:t2’,{STARTROW=>‘20210201_001’,STOPROW=>‘20210301_007’}
|
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9sqlyfCP-1616631213613)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317102656062.png)]
- ==注意==
- 在Hbase数据检索,==尽量走索引查询:按照Rowkey条件查询==
- 尽量避免走全表扫描
- 索引查询:有一本新华字典,这本字典可以根据拼音检索,找一个字,先找目录,找字
- 全表扫描:有一本新华字典,这本字典没有检索目录,找一个字,一页一页找
- ==Hbase所有Rowkey的查询都是前缀匹配==
```
Rowkey的是什么至关重要:20210201_001,时间_用户id
如果我要查询:2021年2月到2021年9月所有的数据
scan 'itcast:t2',{startrow => 202102 ,stoprow = 202110}
走索引查询
如果rowkey的前缀是用户id,001_20210201
如果我要查询:2021年2月到2021年9月所有的数据
scan 'itcast:t2',{columnValuePrefix(time >= 202102 and time <= 202109)}
不走索引
```
## 知识点10:DML命令:delete
- 功能:删除Hbase中的数据
- 语法
```shell
#删除某列的数据
delete tbname,rowkey,cf:col
#删除某个rowkey数据
deleteall tbname,rowkey
#清空所有数据
truncate tbname
示例delete 'itcast:t2','20210101_000','cf3:addr'
deleteall 'itcast:t2','20210101_000'
truncate 'itcast:t2'
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VDtiIwQa-1616631212962)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317104152444.png)]
知识点11:DML命令:incr
功能:一般用于自动计数的,不用记住上一次的值,直接做自增
需求:一般用于做数据的计数
与Put区别
put:需要记住上一次的值是什么put 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT',12
put 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT',13
put 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT',14
incr:不需要知道上一次的值是什么,自动计数incr 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT',12
incr 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT'
incr 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT'
语法incr '表名','rowkey','列族:列'
get_counter '表名','rowkey','列族:列'
示例create 'NEWS_VISIT_CNT', 'C1'
incr 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT',12
get_counter 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT'
incr 'NEWS_VISIT_CNT','0000000001_00:00-01:00','C1:CNT'
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-amWR8SUU-1616631212963)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317104414945.png)]
知识点12:DML命令:count
知识点13:JavaAPI:构建工程依赖
创建工程,以及模块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mg8taowy-1616631212964)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317110507951.png)]
导入Hbase的依赖到模块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tNBmNddM-1616631212965)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317110642956.png)]
将log4j日志记录配置文件放入resources目录下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YfEH6Sbr-1616631212965)(20210317_分布式NoSQL列存储数据库Hbase(二).assets/image-20210317110907228.png)]
知识点14:JavaAPI:构建连接
客户端和服务端模式的代码开发规则
step1:构建连接对象,指定连接服务端地址
step2:调用连接对象的方法,实现需求
step3:释放连接对象
构建连接//todo:1-构建连接对象
//构建配置对象,用于管理当前程序的所有配置:用于加载hbase-default和hbase-site文件
Configuration conf = HBaseConfiguration.create();
//在配置中指定服务端地址:Hbase服务端地址:Zookeeper地址
conf.set("hbase.zookeeper.quorum","node1:2181,node2:2181,node3:2181");
//构建连接对象
Connection conn = ConnectionFactory.createConnection(conf);
知识点15:JavaAPI:DDL
Hbase中的JavaAPI,所有的DDL操作,都必须由管理员对象来实现
构建一个Hbase管理员对象//todo:2-DDL,必须构建管理员
HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
使用管理员对象实现DDL操作/**
* 创建表
* @param admin
* @throws IOException
*/
private void ceateTable(HBaseAdmin admin) throws IOException {
//定义一个表对象:两个列族,basic【3个版本】和other
TableName tbname = TableName.valueOf("itcast:t1");
//先判断表是否存在,如果已经存在,先删除再创建
if(admin.tableExists(tbname)){
//先禁用
admin.disableTable(tbname);
//然后删除
admin.deleteTable(tbname);
}
//构建列族的描述器对象
ColumnFamilyDescriptor basic = ColumnFamilyDescriptorBuilder
.newBuilder(Bytes.toBytes("basic"))//指定列族名称
.setMaxVersions(3)//设置最大存储版本数
.build();
ColumnFamilyDescriptor other = ColumnFamilyDescriptorBuilder
.newBuilder(Bytes.toBytes("other"))
.build();
//构建一个表的描述器对象
TableDescriptor desc = TableDescriptorBuilder
.newBuilder(tbname) //指定表的名称
.setColumnFamily(basic)//指定列族
.setColumnFamily(other)//指定列族
.build();
//创建表
admin.createTable(desc);
}
/**
* 列举所有的表
* @param admin
* @throws IOException
*/
private void listTable(HBaseAdmin admin) throws IOException {
//调用列举表的方法
List<TableDescriptor> tableDescriptors = admin.listTableDescriptors();
//迭代取出每张表的信息
for (TableDescriptor tableDescriptor : tableDescriptors) {
//打印表名
System.out.println(tableDescriptor.getTableName().getNameAsString());
}
}
/**
* 删除NS
* @param admin
*/
private void dropNs(HBaseAdmin admin) throws IOException {
admin.deleteNamespace("bigdata");
}
/**
* 创建NS
* @param admin
*/
private void createNs(HBaseAdmin admin) throws IOException {
//创建一个NS的描述器
NamespaceDescriptor descriptor = NamespaceDescriptor
.create("bigdata")//指定NS的名称
.build();
//调用创建的方法
admin.createNamespace(descriptor);
}
/**
* 用于实现列举当前所有的NS
* @param admin
*/
private void listNs(HBaseAdmin admin) throws IOException {
//调用列举NS的方法
NamespaceDescriptor[] descriptors = admin.listNamespaceDescriptors();
//迭代取出每个NS的信息,打印名称即可
for (NamespaceDescriptor descriptor : descriptors) {
System.out.println(descriptor.getName());
}
}
作业
附录一:Hbase Maven依赖
<repositories>
<repository>
<id>aliyun</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<properties>
<hbase.version>2.1.2</hbase.version>
</properties>
<dependencies>
<!-- Hbase Client依赖 -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>${hbase.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>${hbase.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
附录一:Hbase Maven依赖
<repositories>
<repository>
<id>aliyun</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<properties>
<hbase.version>2.1.2</hbase.version>
</properties>
<dependencies>
<!-- Hbase Client依赖 -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>${hbase.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>${hbase.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>