Hbase实时分布式NoSQL数据库1
-
Hbase入门
- 问题1:Hbase与HDFS、Hive、MySQL有什么区别?
- 定义:Hbase是一个分布式、大数据量实时随机数据读写、面向列的NoSQL数据库
- HDFS:Hbase底层也使用了HDFS,Hbase是实时、数据库,HDFS是离线、文件系统
- Hive:Hbase和Hive底层都基于HDFS,都是类数据库结构,Hive是离线工具数据仓库,Hbase是实时数据库
- MySQL:MySQL是RDBMS【支持SQL,复杂分析,支持完善事务】,Hbase是NoSQL【不支持SQL,不支持复杂分析以及特殊事务】
- 问题2:Hbase为什么读写很快?
- 写:直接写内存,所有删除和修改都是逻辑的,通过插入来实现逻辑删除和逻辑修改
- 读:优先读内存,内存没有再读HDFS:构建有序、列族
- 问题3:什么是Namespace、Table、Rowkey、ColumnFamily、Qualifier、VERSIONS?
- Namespace:就是数据库概念,Hbase自带了一个NS叫做default
- Table:就是表概念,Hbase中表是分布式的,一张表在集群中会对应着多个Region分区,操作表必须通过ns:tbname
- Region:就是分区概念,每张Hbase的表可以对应多个分区,每个分区可以存储在不同节点上,默认每张表只有1个分区
- Rowkey:行健,类似于主键概念,唯一标识一行,也是Hbase唯一索引,Hbase每张表自带这一列,必须指定之一列的值
- ColumnFamily:列族,对列的分组,将拥有相似IO属性的列划分到同一组中,为了提高查询性能
- Qualifier:列标签,就是列的概念,访问Hbase表中列必须通过cf:col
- Versions:多版本,Hbase中一列的数据可以存储多个版本的值,列族级别的属性
- 问题4:Hbase的集群架构以及角色功能是什么?
- Hbase:分布式主从架构
- HMaster:负责管理从节点,负责管理元数据
- HRegionServer:负责存储所有表的Region,提供客户端对Region读写请求,提供分布式内存
- HDFS:作为Hbase底层分布式磁盘存储,当RegionServer内存达到阈值,将数据从内存溢写到HDFS中
- Zookeeper:1-实现辅助选举Active Master,2-存储Hbase管理元数据
- Hbase:分布式主从架构
- 问题1:Hbase与HDFS、Hive、MySQL有什么区别?
-
Hbase的命令
- 问题:常见的命令以及语法有哪些?
- DDL:list_namespace、create_namespace、drop_namespace、list、create、drop、disable、enable、exists
- DML:put、delete、get、scan
- 问题:常见的命令以及语法有哪些?
-
Hbase的Java API
-
问题:Java API规则和类有哪些?
-
基本:构建连接
Configuration conf = HbaseConfiguration.create() conf.set(Hbase服务端就是ZK地址) Connection conn = ConnectionFactory.createConnection(conf)
-
DDL
- step1:先构建管理员对象:HbaseAdmin admin = conn.getAdmin
- step2:调用管理员方法
- admin.createNamesapce
- admin.deleteNamespace
- admin.createTable
- admin.deleteTable
- admin.tableExists
-
DML
- step1:先构建Table对象:Table table = conn.getTable(TableName.valueOf(表名))
- step2:要做什么操作,必须先构建操作的对象
- Put、Get、Delete、Scan
- Hbase中所有的数据都以字节数组方式存储
- 写:Bytes.toBytes(值)
- 读:Bytes.toString(字节数组)
- Cell:代表一列,CellUtil.cloneRow、conleColumnFamilly实现取值
- Result:代表一个Rowkey
- ResultScanner:代表多个Rowkey
- step3:调用操作方法
- table.put
- table.get
- table.delete
- table.getScanner
-
-
``
Apache HBase™ is the Hadoop database, a distributed, scalable, big data store.
Hbase是Hadoop的数据库,分布式的、可扩展的大数据量的存储【HDFS离线场景,适用于一次写入多次读取】
Use Apache HBase™ when you need random, realtime read/write access to your Big Data.
使用Hbase当你需要随机的实时的读写访问的你的大数据量
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.
Hbase是开源的、分布式的、多版本的、NoSQL非关系型数据库诞生自Google的BigTable结构化的分布式存储系统
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.
类似于谷歌的BigTable依赖于Google的GFS,Hbase也需要类型的存储例如Hadoop的HDFS
-
定义:分布式的大数据量实时随机读写的NOSQL数据库
-
诞生
-
存储需求的发展:早期【能实现分布式大数据量存储】、现在【能实现实时大数据量的读写】
-
Hbase的诞生:Google 21世纪前三驾马车【GFS、MapReduce、BigTable】
-
-
功能:提供分布式的、实时的、随机的、大数据量的、结构化数据的、面向列的持久性数据存储
- 列式存储:所有行这一列的数据都存储在一起
- 面向列存储:最小操作单元为列,每一行拥有的列可以不一样
-
场景:大数据量、实时读写的场景
- 时序数据存储:HBase适用于存储和处理大量的时序数据,如传感器数据、日志信息、监控数据等。它可以按照时间戳进行排序和查询,并快速访问最新的数据。
- 实时计算和分析:HBase提供快速的随机读写能力和低延迟的访问性能,使它成为实时计算和分析的理想存储引擎。例如,将实时交易数据存储在HBase中,以支持实时风险管理和即时决策。
- 用户个性化推荐:通过将用户行为数据存储在HBase中,并结合分布式计算引擎进行实时处理,可以构建个性化推荐系统。基于用户的历史行为和偏好,提供针对性的推荐结果。
- 日志分析:企业需要处理大量的日志数据,包括服务器日志、网络日志、安全日志等。HBase可以作为一个高可扩展的存储层,快速存储和查询这些日志数据,便于后续的分析和监控。
- 在线广告投放:HBase可以存储广告主要素材信息和用户的点击数据,用于实时匹配和投放广告。通过查询HBase中的数据,可以快速为用户提供个性化的广告内容。
- 电信和物联网应用:电信行业需要存储大量的用户信息、通话记录和设备状态,而物联网应用需要处理海量的传感器数据。HBase可以满足这两个领域的高吞吐量和低延迟的要求,支持快速访问和查询大规模数据。
知识点04:【掌握】Hbase的存储设计
-
目标:掌握Hbase的存储设计
-
实施
-
问题1:为什么说Hbase是面向列存储的NoSQL数据库?
- 面向行:每次操作的最小单元是一行,例如MySQL
- 操作:insert、delete、update、select
- 影响:至少是一行数据
- 面向列:每次操作的最小单元是一行中的一列,例如Hbase
- 操作:put、delete、get、scan
- 影响:最小是某一行中的某一列的数据
- put:为表中的某一行插入某一列或者更新某一列的值
- delete:删除表中的某一行的某一列
- get/scan:查询表中的某一行的某一列的值
- 特点:每一行可以拥有不同的列
- 面向行:每次操作的最小单元是一行,例如MySQL
-
问题2:为什么Hbase和Hive底层都基于HDFS,但是Hbase却是实时的?
-
原因:Hbase的存储是基于:内存 + HDFS,数据优先读写内存【空间小,易丢失,性能高】
- 写:数据先写入内存,如果内存达到一定条件才写入HDFS
- 读:数据先读取内存,如果内存中没有才从HDFS中读取
-
思想:冷热数据分离,实时场景中新数据才是热数据,产生很久的数据属于冷数据
- 应用场景:实时场景,实时的数据量小,数据一产生立即写入并且立即别读取
- 设计思想:冷热数据分离
- 冷:不被经常使用的数据,产生了一定时间的数据叫做冷数据,HDFS
- 热:经常要被使用的数据,刚产生的数据就是热数据,内存中
-
-
问题3:各自之间的区别?
- Hbase与HDFS
- 共性:本质上Hbase使用的还是HDFS
- HDFS:分布式文件系统【文件】、离线、分布式磁盘、大数据量永久性存储
- Hbase:分布式NoSQL数据库【表】、实时、分布式内存+分布式磁盘【HDFS】、大数据量永久性存储或者临时存储
- Hbase与Hive
- 共性:底层都基于HDFS,都做为Hadoop系列的存储工具
- Hbase:基于hadoop的软件 ,数据库工具, hbase是NoSQL存储容器, 延迟性较低, 接入在线实时业务
- Hive:基于hadoop的软件, 数仓工具 , Hive延迟较高, 接入离线业务, 用于 OLAP操作
- Hbase与MySQL
- 共性:都是数据库,都用于实现数据存储
- Hbase:NoSQL,不支持SQL语句,仅支持单行事务操作,分布式存储 ,面向列操作,不支持join等分析操作
- MySQL:RDBMS,支持SQL ,支持多行事务操作, 中心化存储,面向行操作,支持join等分析操作
- Hbase与HDFS
-
-
小结:掌握Hbase的存储设计
知识点05:【掌握】Hbase的存储对象
-
目标:掌握Hbase的存储对象
- MySQL存储数据是通过Database数据库和Table数据表,那Hbase中怎么实现呢?
-
实施
-
对比
概念 MySQL ElasticSearch Hbase 数据库 database Index Namespace 数据表 table Type table 区别 单节点 分布式 分布式 -
Namespace:命名空间
- 设计:类似于MySQL中databases数据库的概念
- 功能:用于对Hbase的数据存储进行一级划分,不同业务的数据存储在不同的Namespace中
- 规则:Hbase中默认自带了一个ns叫做default
-
Table:表
- 设计:类似于MySQL中table数据表的概念,但是Hbase中的Table是分布式的存储概念,表的数据会被分布式存在多台节点
- 功能:用于对每个ns中的数据进行二级划分,相同业务的不同数据存储在不同的Table中
- 规则:Hbase中的任何一张表必须属于某个ns中,访问表的时候必须使用
ns:table
,除非这张表在default数据库中 - 思考:Hbase表的分布式是怎么体现的?
-
Region:分区
-
规则:Hbase的一张表可以划分成多个Region分区,默认每张表只有1个分区,Hbase会根据分区规则对数据进行不同分区读写
-
设计:类似于HDFS中的Block、ElasticSearch中的Shard、RDD中的Partition,分布式的设计
-
功能:用于将Hbase中的一张表实现分布式存储,一张表可以对应多个分区
-
-
-
小结:掌握Hbase的存储对象
知识点06:【掌握】Hbase的存储概念
-
目标:掌握Hbase的存储概念
-
实施
-
原则:Hbase中有很多不太能理解的设计,设计目的一定是为了加快Hbase读/写[增删改]性能
- 写:直接写内存,本来就很快
-
读:虽然刚写入的数据在内存,但是如果因为数据量或者数据延迟导致了要读取的数据在HDFS,怎么办?
- 索引查询
- 有序文件
- 二进制文件
- 缓存
-
对比
概念 MySQL ElasticSearch Hbase 结构 Row KV KV 组成 字段 DocId + Fields Rowkey + Qualifier 主键 PrimaryKey【可以没有】 DocId【必须有】 Rowkey行健 列族 - - ColumnFamily 字段 Column Fields Qualifier 版本 - - VERSIONS -
Rowkey:行健
- 设计:类似于MySQL中的主键、ElasticSearch中的DocumentId
- 功能:唯一标识Hbase中的一 “ 行 ” 数据,作为Hbase中查询的唯一索引【Hbase中不支持创建索引】
- 规则:Hbase每张表自带行健这一列
- 注意:行健这一列的值必须由用户指定,不能没有,指定的时候需要考虑索引设计问题
-
ColumnFamily:列族/列簇
-
设计:为了提高Hbase查询时的性能,在存储时将数据列进行分组,查询时根据分组,实现快速检索
-
功能:将一张表的不同列划分到不同的组中,物理上相同组的列的数据存储在一起
-
需求:在一张拥有100列的表中,查询某一列的数据
-
没有列族:最大比较次数:100次
-
有了列族:最大比较次数:52次
-
-
规则:每张表在创建时至少要有一个列族,每一列都必须属于表中的某一个列族,一般会将具有相似IO属性的列划分到一组
-
注意:列族的个数必须合理,不能过多也不能过少,一般工作中最多不超过3个
-
-
Qualifier:列标签/列
- 设计:类似于MySQL中的列,更像ElasticSearch中的Fields
- 功能:用于存储每行不同字段的数据,Hbase一张表可以拥有上百万列,每一行的拥有的列也可以不同
- 规则:Hbase中每一列都必须属于表中的某一个列族,访问列时必须通过
cf:col
来访问,列是Hbase表的最小操作单元
-
Versions:多版本
-
设计:为了能够实现数据回溯、并发控制、历史数据查询和分析,Hbase允许一列存储多个版本的值
-
功能:用于实现对每一列存储这一列多个版本的值
-
规则:多版本是列族级别的配置,可以针对每个列族修改,默认每个列族下的所有列只保留1个版本的值
-
思考:某一行的某一列的值可以存储多个版本,那查询的时候显示哪个版本?怎么区分不同的版本值?
- 如果一列有多个版本的值:默认只显示最新版本的值
- Hbase在写入数据的每个版本时,会自动增加数据的Timestamp,用于区分不同的版本
- 最新版本 = 时间最大的版本
-
例如
Rowkey basic basic basic other other ts name age sex phone addr ts zhangsan_20230101 zhangsan 18 male[标记更新] 110 Beijing 2023-01-01 female Sanya 2023-06-06 lisi_20230101 lisi 20 female 119[标记删除] Shanghai 2023-01-01 120 2023-02-01 121 2023-03-01
-
-
思考:Hbase底层的数据到底怎么存储的,为什么Hbase的一张表能够存储上百万列,而且Hbase还能存储多个版本?
-
设计:逻辑行与物理行
- 逻辑行:Hbase的一个Rowkey只是逻辑上的一行,物理上对应着多行数据
- 物理行:Hbase的一个Rowkey的一列是物理上的一行,每一个物理行是一个KV结构
-
结构:Hbase是KV结构的顺序存储,Key:Rowkey + ColumnFamily + Qualifier + Timestamp,Value:存储的值
Key:row + cf + col + ts[降序] Value:值 lisi_20230101 + basic + age + 20230101 20 lisi_20230101 + basic + name + 20230101 lisi lisi_20230101 + basic + sex + 20230101 female lisi_20230101 + other + addr + 20230101 Shanghai lisi_20230101 + other + phone + 20230301 121 lisi_20230101 + other + phone + 20230201 120 lisi_20230101 + other + phone + 20230101 119 zhangsan_20230101 + basic + age + 20230101 18 zhangsan_20230101 + basic + name + 20230101 zhangsan zhangsan_20230101 + basic + sex + 20230601 female zhangsan_20230101 + basic + sex + 20230101 male zhangsan_20230101 + other + addr + 20230601 Sanya zhangsan_20230101 + other + addr + 20230101 Beijing zhangsan_20230101 + other + phone + 20230101 110
-
-
-
小结:掌握Hbase的存储概念
知识点07:【掌握】Hbase的集群架构
-
目标:掌握Hbase的集群架构
-
实施
-
架构:普通分布式主从架构
-
角色
- HMaster:主节点:管理节点,类似于NameNode的设计
- 负责所有从节点的管理
- 负责元数据的管理
- HRegionServer:从节点:存储节点,类似于DataNode设计
-
负责管理每张表的分区数据:Region,类似于DataNode存储每个文件的块
-
对外提供Region的读写请求
-
用于构建分布式内存
-
- HMaster:主节点:管理节点,类似于NameNode的设计
-
组件
- Hbase:通过RegionServer构建分布式内存,对外提供基于内存的读写
- HDFS:构建分布式磁盘,当Hbase中的内存达到一定阈值,将内存的数据溢写到HDFS磁盘上
- Zookeeper:【辅助选举】:多个Master的Active选举,【存储元数据】:Hbase的管理元数据
-
-
小结:掌握Hbase的集群架构
知识点08:【实现】Hbase的集群搭建
-
目标:实现Hbase集群的搭建
-
实施
-
集群环境:Spark集群:100 ~ 102
-
解压安装
-
上传HBASE安装包到第一台机器的/export/software目录下
cd /export/software/ rz
-
解压安装
# 解压 tar -zxf hbase-2.1.0.tar.gz -C /export/server/ # 切换 cd /export/server/hbase-2.1.0/ # 修改权限 chown -R root:root /export/server/hbase-2.1.0/ # 删除文档 rm -rf /export/server/hbase-2.1.0/docs/
-
-
修改配置
-
切换到配置文件目录下
cd /export/server/hbase-2.1.0/conf/
-
修改hbase-env.sh
#28行 export JAVA_HOME=/export/server/jdk #125行 export HBASE_MANAGES_ZK=false
-
修改hbase-site.xml
cd /export/server/hbase-2.1.0/ mkdir datas vim conf/hbase-site.xml
<property> <name>hbase.tmp.dir</name> <value>/export/server/hbase-2.1.0/datas</value> </property> <property> <name>hbase.rootdir</name> <value>hdfs://node1.itcast.cn:8020/hbase</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>node1.itcast.cn,node2.itcast.cn,node3.itcast.cn</value> </property> <property> <name>hbase.unsafe.stream.capability.enforce</name> <value>false</value> </property>
-
修改regionservers
vim conf/regionservers
node1 node2 node3
-
配置环境变量
vim /etc/profile
#HBASE_HOME export HBASE_HOME=/export/server/hbase-2.1.0 export PATH=:$PATH:$HBASE_HOME/bin
source /etc/profile
-
复制jar包
cp lib/client-facing-thirdparty/htrace-core-3.1.0-incubating.jar lib/
-
-
分发
cd /export/server/ scp -r hbase-2.1.0 node2:$PWD scp -r hbase-2.1.0 node3:$PWD
-
服务端启动与关闭
-
step1:启动HDFS【第一台机器】,注意一定要等HDFS退出安全模式再启动Hbase
start-dfs.sh
-
step2:启动ZK
# 先上传资料中的脚本到/export/server/hbase-2.1.0/bin目录下,然后添加执行权限 start-zk-all.sh
-
step3:启动Hbase
start-hbase.sh
-
关闭:先关闭Hbase再关闭zk
stop-hbase.sh stop-zk-all.sh stop-dfs.sh
-
-
测试
- 访问Hbase Web UI【node1:16010】,CDH版本的Hbase会沿用老的端口:10060
-
搭建Hbase HA
-
关闭Hbase所有节点
stop-hbase.sh
-
创建并编辑配置文件
vim conf/backup-masters
node2
-
启动Hbase集群
-
-
测试HA
-
启动两个Master,强制关闭Active Master,观察StandBy的Master是否切换为Active状态
hbase-daemon.sh stop master
-
【测试完成以后,删除配置,只保留单个Master模式】
-
-
-
小结:实现Hbase集群的搭建
【模块二:Hbase的命令】
知识点09:【理解】Hbase的开发场景
-
目标:理解Hbase的开发场景
-
实施
-
场景1:测试开发
-
需求:一般用于测试开发或者实现DDL操作
-
实现:Hbase shell命令行
-
用法:hbase shell
-
命令
- 查看帮助:help
- 查看命令的用法:help ‘command’
- 退出:exit
-
-
场景2:生产开发
-
需求:一般用于生产开发,通过MapReduce或者Spark等程序读写Hbase,类似于JDBC
-
实现:分布式计算程序通过Java API读写Hbase,实现数据处理
-
用法:在MapReduce或者Spark中集成API
-
场景3:集群管理
-
应用场景:运维做运维集群管理,我们开发用的不多
-
需求:封装Hbase集群管理命令脚本,自动化执行
-
实现:通过Hbase的客户端运行命令文件,通过调度工具进行调度实现定时运行
-
用法:hbase shell 文件路径
-
step1:将Hbase的命令封装在一个文件中:vim /export/data/hbase.txt
list exit
-
step2:运行Hbase命令文件
hbase shell /export/data/hbase.txt
-
step3:封装到脚本
#!/bin/bash hbase shell /export/data/hbase.txt
-
-
注意:所有的Hbase命令文件,最后一行命令必须为exit,不然就不会退出
-
-
-
-
小结:理解Hbase的开发场景
知识点10:【掌握】Hbase DDL Namespace
-
目标:掌握Hbase DDL Namespace的使用
-
实施
-
列举所有Namespace
-
命令:list_namespace
-
语法
list_namespace
-
示例
list_namespace
-
-
列举某个NameSpace中的表
-
命令:list_namespace_tables
-
语法
list_namespace_tables 'Namespace的名称'
-
示例
list_namespace_tables 'hbase'
-
-
创建
-
命令:create_namespace
-
语法
create_namespace 'Namespace的名称'
-
示例
create_namespace 'heima' create_namespace 'itcast'
-
-
删除
-
命令:drop_namespace
-
注意:只能删除空数据库,如果数据库中存在表,不允许删除
-
语法
drop_namespace 'Namespace的名称'
-
示例
drop_namespace 'itcast' drop_namespace 'heima'
-
-
-
小结:掌握Hbase DDL Namespace的使用
知识点11:【掌握】Hbase DDL Table
-
目标:掌握Hbase DDL Table的使用
-
实施
-
列举
-
命令:list
-
语法:list
-
示例
list
-
-
创建
-
命令:create
-
注意:建表时必须指定表名及至少一个列族
- SQL:create table if not exists dbname.tbname(id int, name string);
- Hbase:nsname:tbname + cf
-
语法
#表示在ns1的namespace中创建一张表t1,这张表有一个列族叫f1,这个列族中的所有列可以存储5个版本的值 create 'ns1:t1', {NAME => 'f1', VERSIONS => 5}, {NAME => 'f2'} #在default的namespace中创建一张表t1,这张表有三个列族,f1,f2,f3,每个列族的属性都是默认的 create 't1', 'f1', 'f2', 'f3'
-
示例
#如果需要更改列族的属性,使用这种写法 create 't1',{NAME=>'cf1'},{NAME=>'cf2',VERSIONS => 3} #如果不需要更改列族属性 create_namespace 'itcast' create 'itcast:t2','cf1','cf2','cf3' # create 't1',{NAME=>'cf1'},{NAME=>'cf2'},{NAME=>'cf3'}
-
-
查看
-
命令:desc
-
语法
desc '表名'
-
示例
desc 't1'
-
-
删除
-
命令:drop
-
语法
drop '表名'
-
示例
drop 't1'
-
注意:如果要对表进行删除,必须先禁用表,再删除表
-
-
禁用/启用
-
命令:disable / enable
-
功能:Hbase为了避免修改或者删除表,影响这张表正在对外提供读写服务
-
规则:修改或者删除表时,必须先禁用表,表示这张表暂时不能对外提供服务
- 如果是删除:禁用以后删除
- 如果是修改:先禁用,然后修改,修改完成以后启用
-
语法
disable '表名' enable '表名'
-
示例
disable 't1' enable 't1'
-
-
判断存在
-
命令:exists
-
语法
exists '表名'
-
示例
exists 't1'
-
-
-
小结:掌握Hbase DDL Table的使用
知识点12:【理解】Hbase DML Put
-
目标:理解Hbase DML Put操作
-
实施
-
功能:插入 / 更新数据【某一行的某一列】
-
语法
#表名+rowkey+列族+列+值 put 'ns:tbname','rowkey','cf:col','value'
-
示例
disable 'itcast:t2' drop 'itcast:t2' create 'itcast:t2','cf1',{NAME=>'cf3',VERSIONS => 2}
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' put 'itcast:t2','20210101_000','cf3:addr','guangzhou' scan 'itcast:t2',{VERSIONS=>10}
-
观察结果
-
现象1:Hbase表会自动按照底层的Key【rowkey+cf+col+ts】构建字典有序:逐位比较
- 设计目标:加快数据的查询,基于有序的数据查询更快
-
现象2:没有物理更新和删除:通过插入来代替的,实现逻辑更新和删除,做了标记不再显示
- 设计目标:提高数据写入的性能,通过插入数据来代替物理删除和物理修改
-
-
-
小结:理解Hbase DML Put操作
知识点13:【理解】Hbase DML Get
-
目标:理解Hbase DML Get
-
实施
-
功能:读取某个Rowkey的数据
- 缺点:get命令最多只能返回一个rowkey的数据,根据Rowkey进行检索数据
- 优点:Get是Hbase中查询数据最快的方式【Rowkey是Hbase唯一索引】,并不是最常用的方式
-
语法
get 表名 rowkey [列族,列] get 'ns:tbname','rowkey' get 'ns:tbname','rowkey',[cf] get 'ns:tbname','rowkey',[cf:col]
-
示例
get 'itcast:t2','20210201_001' get 'itcast:t2','20210201_001','cf1' get 'itcast:t2','20210201_001','cf1:name'
-
-
小结:理解Hbase DML Get
知识点14:【理解】Hbase DML Delete
-
目标:理解Hbase DML delete
-
实施
-
功能:删除Hbase中的数据
-
语法
#删除某列的数据 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'
-
-
小结:理解Hbase DML delete
知识点15:【理解】Hbase DML Scan
-
目标:理解Hbase DML Scan
-
实施
-
功能:根据条件匹配读取多个Rowkey的数据
-
语法
#读取整张表的所有数据 scan 'tbname'//一般不用 #根据条件查询:工作中主要使用的场景 scan 'tbname',{Filter} //用到最多
-
示例
-
插入模拟数据
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','20210201_001','cf1:id','001' put 'itcast:t2','20210101_000','cf1:name','laoer' put 'itcast:t2','20210101_000','cf3:addr','bejing' put 'itcast:t2','20210901_007','cf1:name','laosan' put 'itcast:t2','20210901_007','cf3:addr','bejing' put 'itcast:t2','20200101_004','cf1:name','laosi' put 'itcast:t2','20200101_004','cf3:addr','bejing' put 'itcast:t2','20201201_005','cf1:name','laowu' put 'itcast:t2','20201201_005','cf3:addr','bejing'
-
查看Scan用法
scan 't1', {ROWPREFIXFILTER => 'row2', FILTER => " (QualifierFilter (>=, 'binary:xyz')) AND (TimestampsFilter ( 123, 456))"}
-
测试Scan的使用
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'} # 不走索引的 scan 'itcast:t2',{FILTER => "QualifierFilter (>=, 'binary:b')"}
-
-
在Hbase数据检索,尽量走索引查询:按照Rowkey前缀条件查询
-
尽量避免走全表扫描,优先使用索引Rowkey查询
-
Hbase所有Rowkey的查询都是前缀匹配,只有按照前缀匹配才走索引
-
-
-
小结:理解Hbase DML Scan
知识点16:【理解】Hbase DML incr、count
-
目标:理解Hbase DML incr、count的使用
-
实施
-
incr:自动计数命令
-
功能:一般用于自动计数的,不用记住上一次的值,直接做自增
-
场景:一般用于做数据的计数
-
思考:与Put区别
-
put:需要记住上一次的值是什么
-
incr:不需要知道上一次的值是什么,自动计数
-
-
语法
incr '表名','rowkey','列族:列' get_counter '表名','rowkey','列族:列'
-
示例
create 'NEWS_VISIT_CNT', 'C1' incr 'NEWS_VISIT_CNT','20210101_001','C1:CNT',12 get_counter 'NEWS_VISIT_CNT','20210101_001','C1:CNT' incr 'NEWS_VISIT_CNT','20210101_001','C1:CNT'
-
-
count:统计命令
-
功能:统计某张表的行数【rowkey的个数】
-
语法
count '表名'
-
示例
count 'itcast:t2'
-
-
面试题:Hbase中如何统计一张表的行数最快
-
方案一:分布式计算程序,读取Hbase数据,统计rowkey的个数
#在第一台机器启动 start-yarn.sh #在第一台机器运行 hbase org.apache.hadoop.hbase.mapreduce.RowCounter 'itcast:t2'
-
方案二:count命令,相对比较常用,速度中等
count 'itcast:t2'
-
方案三:协处理器,最快的方式
- 类似于Hive中的UDF,自己开发一个协处理器,监听表,表中多一条数据,就加1
- 直接读取这个值就可以得到行数了
-
-
-
小结:理解Hbase DML incr、count的使用
【模块三:Hbase的Java API】
知识点17:【掌握】Java API:Connection
-
目标:掌握JavaAPI Connection
-
实施
package bigdata.itcast.cn.hbase.client; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.junit.After; import org.junit.Before; import java.io.IOException; /** * Todo:通过Java客户端API实现对HbaseDDL操作 * Namespace:创建、删除 * Table:创建、删除 */ public class HbaseDDLClientTest { // 定义一个连接对象 Connection conn = null; /** * 用于获取一个Hbase的连接 * @throws IOException */ @Before public void getHbaseConnection() throws IOException { // 构建一个配置对象,管理当前程序的配置 Configuration conf = HBaseConfiguration.create(); // 在配置中指定Hbase地址:任何一个Hbase客户端要想访问Hbase服务端都要连接Zookeeper conf.set("hbase.zookeeper.quorum", "node1.itcast.cn,node2.itcast.cn,node3.itcast.cn"); // 获取一个hbase连接对象 conn = ConnectionFactory.createConnection(conf); } /** * 程序结束释放Hbase所有连接 * @throws IOException */ @After public void closeConnection() throws IOException { conn.close(); } }
-
小结:掌握JavaAPI Connection
知识点18:【掌握】Java API:DDL
-
目标:掌握Java API DDL
-
实施
-
构建管理员:Java API中所有的DDL操作都是由管理员对象构建的
// 在Hbase的Java API中,如果要实现DDL操作,必须先构建Hbase的管理员对象HbaseAdmin public HBaseAdmin getHbaseAdmin() throws IOException { //从连接中获取管理员对象 HBaseAdmin admin = (HBaseAdmin) conn.getAdmin(); return admin; }
-
实现DDL管理:创建、删除NS和创建、删除Table
package bigdata.itcast.cn.hbase.client; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.util.Bytes; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; /** * Todo:通过Java客户端API实现对HbaseDDL操作 * Namespace:创建、删除 * Table:创建、删除 */ public class HbaseDDLClientTest { // 定义一个连接对象 Connection conn = null; /** * 用于获取一个Hbase的连接 * @throws IOException */ @Before public void getHbaseConnection() throws IOException { // 构建一个配置对象,管理当前程序的配置 Configuration conf = HBaseConfiguration.create(); // 在配置中指定Hbase地址:任何一个Hbase客户端要想访问Hbase服务端都要连接Zookeeper conf.set("hbase.zookeeper.quorum", "node1.itcast.cn,node2.itcast.cn,node3.itcast.cn"); // 获取一个hbase连接对象 conn = ConnectionFactory.createConnection(conf); } public HBaseAdmin getHbaseAdmin() throws IOException { // 从连接中获取一个管理员 HBaseAdmin admin = (HBaseAdmin) conn.getAdmin(); // 返回管理员对象 return admin; } /** * 创建NS * @throws IOException */ @Test public void createNs() throws IOException { // 获取管理员 HBaseAdmin admin = getHbaseAdmin(); // 所有你要的DDL操作都在admin的方法中 // 构建一个NS对象 NamespaceDescriptor descriptor = NamespaceDescriptor .create("heima") .build(); // 创建NS admin.createNamespace(descriptor); // 释放资源 admin.close(); } /** * 删除NS * @throws IOException */ @Test public void dropNs() throws IOException { // 获取管理员 HBaseAdmin admin = getHbaseAdmin(); // 所有你要的DDL操作都在admin的方法中 admin.deleteNamespace("heima"); // 释放资源 admin.close(); } @Test public void createHbaseTable() throws IOException { // 获取管理员 HBaseAdmin admin = getHbaseAdmin(); // 建表:如果表存在,就先删除,itcast:t1, 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 table = TableDescriptorBuilder .newBuilder(tbname) // 指定表名 .setColumnFamily(basic) // basic .setColumnFamily(other) // other .build(); // 创建表 admin.createTable(table); // 释放资源 admin.close(); } /** * 程序结束释放Hbase所有连接 * @throws IOException */ @After public void closeConnection() throws IOException { conn.close(); } }
-
-
小结:掌握Java API DDL
知识点19:【掌握】Java API:Put
-
目标:掌握Java API Put
-
实施
-
构建HTable:DML操作都必须构建Hbase表的对象来进行操作
//构建Hbase表的实例 public Table getHbaseTable() throws IOException { // 构建表名 TableName tbname = TableName.valueOf("itcast:t1"); // 获取一个Hbase表的对象 Table table = conn.getTable(tbname); return table; }
-
实现Put
@Test public void testPut() throws IOException { // 获取表的对象 Table table = getHbaseTable(); // 构建Put类的对象:一个Put只能操作一个Rowkey Put put = new Put(Bytes.toBytes("20220806_888")); // 配置put对象 put.addColumn(Bytes.toBytes("basic"), Bytes.toBytes("name"), Bytes.toBytes("zhangsan")); put.addColumn(Bytes.toBytes("basic"), Bytes.toBytes("age"), Bytes.toBytes("18")); put.addColumn(Bytes.toBytes("basic"), Bytes.toBytes("sex"), Bytes.toBytes("male")); put.addColumn(Bytes.toBytes("other"), Bytes.toBytes("phone"), Bytes.toBytes("110")); // 对表执行put操作 table.put(put); // 释放资源 table.close(); }
-
-
小结:掌握Java API Put
知识点20:【掌握】Java API:Get
-
目标:掌握Java API Get
-
实施
-
插入数据
put 'itcast:t1','20210201_000','basic:name','laoda' put 'itcast:t1','20210201_000','basic:age',18 put 'itcast:t1','20210101_001','basic:name','laoer' put 'itcast:t1','20210101_001','basic:age',20 put 'itcast:t1','20210101_001','basic:sex','male' put 'itcast:t1','20210228_002','basic:name','laosan' put 'itcast:t1','20210228_002','basic:age',22 put 'itcast:t1','20210228_002','other:phone','110' put 'itcast:t1','20210301_003','basic:name','laosi' put 'itcast:t1','20210301_003','basic:age',20 put 'itcast:t1','20210301_003','other:phone','120' put 'itcast:t1','20210301_003','other:addr','shanghai'
-
实现Get
@Test public void testGet() throws IOException { // 获取表的对象 Table table = getHbaseTable(); // 构建Get类的对象 Get get = new Get(Bytes.toBytes("20220806_888")); // 配置Get // get.addFamily(); // 指定读取哪个列族 // get.addColumn(); // 指定读取哪一列 /* * Result:一个Result代表Hbase中一条Rowkey的所有数据 * Cell:一个Cell代表Hbase中一个Rowkey中的一列的数据 * CellUtil:专门为Cell对象设计的,用于从Cell取出元素 */ Result result = table.get(get); // 取出每一列的数据 for(Cell cell : result.rawCells()){ System.out.println("=============================================="); // 获取这个Cell中的每个值进行输出: 20220806_888 column=basic:age, timestamp=1691918512803, value=18 System.out.println( Bytes.toString(CellUtil.cloneRow(cell)) + "\t" + Bytes.toString(CellUtil.cloneFamily(cell)) + "\t" + Bytes.toString(CellUtil.cloneQualifier(cell)) + "\t" + Bytes.toString(CellUtil.cloneValue(cell)) + "\t" + cell.getTimestamp() ); } // 释放资源 table.close(); }
-
-
小结:掌握Java API Get
知识点21:【掌握】Java API:Delete
-
目标:掌握Java API Delete
-
实施
@Test public void testDelete() throws IOException { // 获取表的对象 Table table = getHbaseTable(); // 构建Delete对象 Delete delete = new Delete(Bytes.toBytes("20220806_888")); // 配置delete delete.addColumn(Bytes.toBytes("basic"), Bytes.toBytes("sex")); // 删除最新版本 delete.addColumns(Bytes.toBytes("basic"), Bytes.toBytes("sex")); // 删除所有版本 // 让表执行delete table.delete(delete); // 释放资源 table.close(); }
-
小结:掌握Java API Delete
知识点22:【掌握】Java API:Scan
-
目标:掌握Java API Scan
-
实施
-
Scan
@Test public void testScan() throws IOException { // 获取表的对象 Table table = getHbaseTable(); // 构建Scan类的对象 Scan scan = new Scan(); /* * ResultScanner:表示多个Rowkey的数据,是Result对象的集合 * Result:一个Result代表Hbase中一条Rowkey的所有数据 * Cell:一个Cell代表Hbase中一个Rowkey中的一列的数据 * CellUtil:专门为Cell对象设计的,用于从Cell取出元素 */ ResultScanner scanner = table.getScanner(scan); // 循环取出每个Rowkey for(Result result: scanner){ System.out.println("=============================================="); System.out.println(Bytes.toString(result.getRow())); // 循环取出每个Rowkey的每一列的数据 // 取出每一列的数据 for(Cell cell : result.rawCells()){ // 获取这个Cell中的每个值进行输出: 20220806_888 column=basic:age, timestamp=1691918512803, value=18 System.out.println( Bytes.toString(CellUtil.cloneRow(cell)) + "\t" + Bytes.toString(CellUtil.cloneFamily(cell)) + "\t" + Bytes.toString(CellUtil.cloneQualifier(cell)) + "\t" + Bytes.toString(CellUtil.cloneValue(cell)) + "\t" + cell.getTimestamp() ); } } // 释放资源 table.close(); }
-
Scan + Filter
package bigdata.itcast.cn.hbase.client; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.filter.*; import org.apache.hadoop.hbase.util.Bytes; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; /** * @ClassName HbaseScanFilterTest * @Description TODO 用于测试通过Hbase Java API 实现 Scan + Filter * @Create By Frank */ public class HbaseScanFilterTest { //构建Hbase连接的对象 Connection conn = null; // todo:1-构建连接 @Before public void getHbaseConnection() throws IOException { //构建一个配置对象 Configuration conf = HBaseConfiguration.create(); //配置Hbase服务端地址:任何一个Hbase客户端都要连接Zookeeper conf.set("hbase.zookeeper.quorum","node1,node2,node3"); //windows必须要能解析地址以及node1.itcast.cn //赋值 conn = ConnectionFactory.createConnection(conf); } // todo:2-从连接中获取操作对象,实现操作 public Table getHbaseTable() throws IOException { // 构建表名 TableName tbname = TableName.valueOf("itcast:t1"); // 获取一个Hbase表的对象 Table table = conn.getTable(tbname); return table; } @Test // Scan语法:scan ns:tbname filter public void testScanFilter() throws IOException { // 获取表的对象 Table table = getHbaseTable(); // 构建Scan对象 Scan scan = new Scan(); //todo:需求1:查询2021年1月和2月的数据 // scan.withStartRow(Bytes.toBytes("202101")); // scan.withStopRow(Bytes.toBytes("202103")); //todo:需求2:查询2021年的所有数据 // Filter prefixFilter = new PrefixFilter(Bytes.toBytes("2021")); //todo:需求3:查询所有age = 20的数据:select * from table where age = 20 Filter valueFilter = new SingleColumnValueFilter( Bytes.toBytes("basic"), Bytes.toBytes("age"), CompareOperator.EQUAL, Bytes.toBytes("20") ); //todo:需求4:查询所有数据的name和age这两列:select name,age from table byte[][] prefixes = { Bytes.toBytes("name"), Bytes.toBytes("age") }; Filter columnFilter = new MultipleColumnPrefixFilter(prefixes); //todo:需求5:查询所有年age = 20的人的name和age FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL); filterList.addFilter(valueFilter); filterList.addFilter(columnFilter); //让Scan加载过滤器 scan.setFilter(filterList); // 对表执行Scan操作 /** * ResultScanner:Hbase JavaAPI中用于封装多个Rowkey的数据的对象,一个ResultScanner对象代表多个Rowkey的聚合 * Result:Hbase Java API中用于封装一个Rowkey的数据的对象,一个Result对象就代表一个Rowkey * Cell:Hbase Java API中用于封装一列的数据的对象,一个Cell对象就代表一列 */ ResultScanner scanner = table.getScanner(scan); // 输出每个Rowkey的每一列的数据 for (Result rs : scanner) { // 将这个rowkey的每一列打印出来 = 要将这个Result对象中的Cell数组中的每个Cell对象中的值取出来 for(Cell cell : rs.rawCells() ){ //打印每一列的内容:rowkey、cf、col、value、ts System.out.println( Bytes.toString(CellUtil.cloneRow(cell)) + "\t" + Bytes.toString(CellUtil.cloneFamily(cell)) + "\t" + Bytes.toString(CellUtil.cloneQualifier(cell)) + "\t" + Bytes.toString(CellUtil.cloneValue(cell)) + "\t" + cell.getTimestamp() ); } System.out.println("+========================================================+"); } // 释放资源 table.close(); } // todo:3-释放资源连接 @After public void closeConn() throws IOException { conn.close(); } }
-
-
小结:掌握Java API Scan
附录一:Hbase Maven依赖
<repositories>
<repository>
<id>aliyun</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-mapreduce</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-jobclient</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-auth</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- JUnit 4 依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>
原文地址:https://blog.csdn.net/Amzmks/article/details/143718130
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!