分布式NoSQL列存储数据库Hbase Java API(三)
文章目录
[*]分布式NoSQL列存储数据库Hbase(三)
[*]
[*]知识点01:课程回顾
[*]知识点02:课程目标
[*]知识点03:Java API:DML:Table
[*]知识点04:Java API:DML:Put
[*]知识点05:Java API:DML:Get
[*]知识点06:Java API:DML:Delete
[*]知识点07:Java API:DML:Scan
[*]知识点08:Java API:DML:Filter
[*]知识点09:存储设计:存储架构
[*]知识点10:存储设计:Table、Region、RegionServer的关系
[*]知识点11:存储设计:Region的划分规则
[*]知识点12:存储设计:Region内部存储结构
[*]知识点13:存储设计:HDFS中的存储结构
[*]知识点11:存储设计:Region的划分规则
[*]知识点12:存储设计:Region内部存储结构
[*]知识点13:存储设计:HDFS中的存储结构
分布式NoSQL列存储数据库Hbase(三)
知识点01:课程回顾
[*] Hbase使用场景
[*] 集群管理:定时调度管理的脚本
[*]定时调度:Azkaban、Oozie、Linux Crontab
[*]Hbase脚本
[*]将Hbase命令写入一个文件
[*]hbase shell运行文件即可
[*] 测试开发:Hbase命令
[*] DDL
[*]list_namespace/create_namespace
[*]create/list/desc
[*] DML
[*] put:插入、更新
[*] 插入:每次是为每行插入一列
[*] 更新:通过插入数据来代替了更新,用于提高性能
[*] 语法
put表rowkey列族:列值
[*] delete:删除数据
[*]delete:删除列
[*]deleteall:删除行
[*]truncate:清空表
[*] get:获取某个rowkey的数据
[*] 优点:查询数据最快的方式,根据rowkey进行查询
[*]rowkey是Hbase中的唯一索引
[*] 缺点
[*]get最多返回一个rowkey的所有列
[*] 语法
get表名rowkey【列族:列】
[*] scan:查询符合条件的数据
[*] 优点:返回需要的多条Hbase的数据
[*] 缺点:很多情况下是不走索引【不能根据rowkey进行检索】
[*] 语法
scan 表名
scan 表名 + Filter
[*] 生产开发:JavaAPI
[*] Connection:连接对象
[*]Configuration:配置管理对象
[*] HbaseAdmin:Hbase管理员对象:用于实现DDL操作
知识点02:课程目标
[*] Hbase JavaAPI实现DML操作【重点内容】
[*]put:数据的写入或者更新
[*]get:查询数据
[*]delete:删除数据
[*]scan:扫描数据
[*]Filter:过滤器
[*] Hbase存储设计【掌握原理】
[*] 表、RegionServer关系?
[*] 表的分布式如何实现的?
[*]Region的划分规则?
[*]数据如何决定进入哪个分区哪?
[*] 分区内部是如何存储数据的?
知识点03:Java API:DML:Table
[*] 需求:通过JavaAPI实现对Hbase的DML操作
[*] 分析
[*]step1:构建连接对象
[*]step2:构建Table对象
[*]所有的DML操作,必须构建一个表的对象
[*] 实现
//todo:1-构建一个连接对象
Configuration conf = HBaseConfiguration.create();
//指定Hbase集群的服务端地址:给定ZK的地址
conf.set("hbase.zookeeper.quorum","node1:2181,node2:2181,node3:2181");
Connection conn = ConnectionFactory.createConnection(conf);
//todo:2-所有的DML必须构建一个Table表的对象
//构建一个表的对象
TableName tbname = TableName.valueOf("itcast:t1");
Table table = conn.getTable(tbname);
[*] 总结
[*]step1:先构建一个连接对象:Connection
[*]step2:根据所做的操作决定构建哪种对象
[*]DDL:HbaseAdmin
[*]DML:Table
知识点04:Java API:DML:Put
[*] 需求:JavaAPI实现往Hbase表中写入数据
put表rowkey列族:列值
[*] 分析
[*]step1:Hbase中实现put操作,需要构建Put对象
[*]step2:为Put对象添加列族、列名、值
[*]step3:对表执行put操作
[*] 实现
/**
* 用于实现使用Put插入数据到表中:put表rowkey列族:列值
* @param table
*/
private void putData(Table table) throws IOException {
//step1:构建Put对象,必须指定插入的rowkey的数据
Put put = new Put(Bytes.toBytes("20201001_888"));
//step2:初始化put,添加列族、列、值
put.addColumn(
Bytes.toBytes("basic"),//指定列族
Bytes.toBytes("name"),//指定列的名称
Bytes.toBytes("laoba")//指定列的值
);
//step3:让表执行put操作
table.put(put);
}
[*] 总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a57OCTc7-1616631335573)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318084424081.png)]
[*]Put对象:专门用于往Hbase写入数据的对象
[*]指定Rowkey,添加列族、列、值信息
[*]table.put
知识点05:Java API:DML:Get
[*] 需求:JavaAPI实现从Hbase表中读取某个Rowkey的数据
get 表名rowkey【列族,列】
[*] 分析
[*] step1:Hbase中实现get操作,需要构建Get对象
[*] step2:为Get对象添加列族、列名
[*] step3:对表执行get操作,获取返回值,打印输出
table.get(Get)
[*] 实现
/**
* 使用Get查询Hbase表中的数据:get 表名rowkey【列族,列】
* @param table
*/
private void getData(Table table) throws IOException {
//step1:构建Get对象,必须指定Rowkey
Get get = new Get(Bytes.toBytes("20201001_888"));
//step2:可选的,配置Get需要的参数:列族、列
// get.addColumn()//指定获取某一列的数据
// get.addFamily()//指定获取某个列族的数据
//step3:表执行get操作
Result result = table.get(get);//Get操作的返回值为Result类型对象
/**
* 迭代输出Result对应的rowkey中的每一列的数据,一个Rowkey包含很多列,循环迭代输出每一列的数据
* Result:一个Result对象就是一个Rowkey的数据
* Cell:一个Cell代表一个rowkey中一列的数据
* 一个Result对象中会包含多个Cell
*/
for(Cell cell : result.rawCells()){
//输出每一列Cell对象中的数据:20201001_888column=basic:age, timestamp=1616029665232, value=20
System.out.println(
Bytes.toString(CellUtil.cloneRow(cell)) //获取这一列的rowkey,转换为字符串类型
+"\t"+
Bytes.toString(CellUtil.cloneFamily(cell)) //获取这一列的列族,转换为字符串类型
+"\t"+
Bytes.toString(CellUtil.cloneQualifier(cell)) //获取这一列的名称,转换为字符串类型
+"\t"+
Bytes.toString(CellUtil.cloneValue(cell)) //获取这一列的值,转换为字符串类型
+"\t"+
cell.getTimestamp() //获取时间戳
);
}
}
[*] 总结
[*]step1:先构建Get
[*]step2:执行Get,得到返回值
[*]Result:一个Result就是一个Rowkey的数据,包含一个Cell数组
[*]Cell:一个Cell就是一列的数据
知识点06:Java API:DML:Delete
[*] 需求:JavaAPI实现从Hbase表删除某个Rowkey的某列的数据
[*] 分析
[*] step1:Hbase中实现delete操作,需要构建Delete对象
[*] step2:为Delete对象添加列族、列名
[*] step3:对表执行delete操作
table.delete(Delete)
[*] 实现
/**
* 删除某个Rowkey的某一列的数据:delete表名 rowkey 列族:列
* @param table
*/
private void deleteData(Table table) throws IOException {
//step1:构建删除对象
Delete delete = new Delete(Bytes.toBytes("20201001_888"));
//step2:添加删除配置
// delete.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name")); //只删除最新版本
delete.addColumns(Bytes.toBytes("basic"),Bytes.toBytes("name")); //删除所有版本
//step3:执行删除
table.delete(delete);
}
[*] 总结
[*]step1:构建Delete对象
[*]step2:根据需求调用配置方法:添加列族、列
[*]step3:表对象指定delete对象即可
知识点07:Java API:DML:Scan
[*] 需求:JavaAPI实现从Hbase表中读取所有数据
scan 表
scan 表 + filter
[*] 分析
[*]step1:Hbase中实现scan操作,需要构建Scan对象
[*]step2:对表执行scan操作
[*]step3:获取返回值,取出每个Rowkey的数据,打印输出
[*] 实现
/**
* 通过Scan,进行Hbase表的数据查询:scan 表
* @param table
*/
private void scanData(Table table) throws IOException {
//step1:构建Scan对象
Scan scan = new Scan();
//step2:执行scan:返回值是ResultScanner,包含了多个Rowkey的数据
ResultScanner rsScan = table.getScanner(scan);
/**
* ResultScanner:包含多个Rowkey的数据,包含了多个Result对象:Iterator<Result>
* Result:一个Rowkey的数据,包含了这个Rowkey多列的数据:Cell[]
* Cell :一列的数据
*/
//step3:打印数据
//先获取每个rowkey
for(Result rs:rsScan){
//直接输出当前rowkey的值
System.out.println(Bytes.toString(rs.getRow()));
//再获取每个rowkey中的每一列
for(Cell cell : rs.rawCells()){
//输出每一列Cell对象中的数据:20201001_888column=basic:age, timestamp=1616029665232, value=20
System.out.println(
Bytes.toString(CellUtil.cloneRow(cell)) //获取这一列的rowkey,转换为字符串类型
+"\t"+
Bytes.toString(CellUtil.cloneFamily(cell)) //获取这一列的列族,转换为字符串类型
+"\t"+
Bytes.toString(CellUtil.cloneQualifier(cell)) //获取这一列的名称,转换为字符串类型
+"\t"+
Bytes.toString(CellUtil.cloneValue(cell)) //获取这一列的值,转换为字符串类型
+"\t"+
cell.getTimestamp() //获取时间戳
);
}
System.out.println("----------------------------------------------------------------------");
}
}
[*] 总结
[*]step1:先构建Scan对象
[*]step2:执行Scan操作
[*]step3:返回值
[*]ResultScanner:包含多个Rowkey的数据的集合
[*]Iter《Result》
[*]Result:一个Rowkey的数据
[*]Cell[]
[*]Cell:一列的数据
知识点08:Java API:DML:Filter
[*] 需求:JavaAPI实现从Hbase表中根据条件读取部分
[*]需求1:查询2021年1月和2月的数据
[*]需求2:查询2021年的所有数据
[*]需求3:查询所有age = 20的数据
[*]需求4:查询所有数据的name和age这两列
[*]需求5:查询所有年age = 20的人的name和age
[*] 分析
[*] Rowkey的设计:时间【年月日】+id
[*]Rowkey整体有序
[*]前缀匹配
[*] 需求1
[*]StartRow = 》202101
[*]包含
[*]StopRow = 》202103
[*]不包含
[*] 需求2
[*] 方案一:使用startrow = 2021,stoprow = 2022
[*] 方案二:使用Filter:PrefixFilter,Rowkey的前缀过滤器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MfZFeVn-1616631335575)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318103200422.png)]
[*]构建过滤器,指定Rowkey前缀
[*]Scan加载过滤器,返回所有符合rowkey前缀的过滤器
[*] 需求三:查询所有age = 20的数据
where age = 20
[*]Filter:列值过滤器
[*]SingleColumnValueFilter:对某一列的值进行过滤
[*]指定列值过滤器:哪个列族下的哪一列的值等于什么值
[*]scan加载过滤器
[*] 需求4:查询所有数据的name和age这两列
select name ,age from table
[*]Filter:多列前缀过滤器
[*]MutipleColumnPrefixFIlter:用于将每条数据中指定的列过滤出来
[*]指定需要过滤哪些列
[*]scan加载过滤器即可
[*] 需求5:查询所有年age = 20的人的name和age
select name,age from table where age = 20
[*]支持组合过滤器:FilterList
[*]列的过滤:MutipleColumnPrefixFIlter
[*]列值过滤:SingleColumnValueFilter
[*]构建两个过滤器,将两个过滤器组合放入过滤器集合
[*]Scan加载过滤器集合
[*] 实现
[*] 批量写入数据到Hbase
/**
* 批量写入数据到Hbase
* @param table
*/
private void putListData(Table table) throws IOException {
//step1:构建Put对象,一个Put对象用于表示一个Rowkey写入的数据
Put put1 = new Put(Bytes.toBytes("20210101_001"));
Put put2 = new Put(Bytes.toBytes("20210201_002"));
Put put3 = new Put(Bytes.toBytes("20210301_003"));
//step2:为Put添加这个Rowkey的每一列
put1.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"),Bytes.toBytes("laoda"));
put1.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("age"),Bytes.toBytes("18"));
put1.addColumn(Bytes.toBytes("other"),Bytes.toBytes("phone"),Bytes.toBytes("110"));
put1.addColumn(Bytes.toBytes("other"),Bytes.toBytes("addr"),Bytes.toBytes("shanghai"));
put2.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"),Bytes.toBytes("laoer"));
put2.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("age"),Bytes.toBytes("20"));
put2.addColumn(Bytes.toBytes("other"),Bytes.toBytes("phone"),Bytes.toBytes("120"));
put3.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("name"),Bytes.toBytes("laosan"));
put3.addColumn(Bytes.toBytes("basic"),Bytes.toBytes("age"),Bytes.toBytes("22"));
put3.addColumn(Bytes.toBytes("other"),Bytes.toBytes("addr"),Bytes.toBytes("beijing"));
//step3:将多个Put封装到List中
List<Put> puts = new ArrayList<Put>();
puts.add(put1);
puts.add(put2);
puts.add(put3);
//step4:执行PutList
table.put(puts);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijNYbrbY-1616631335576)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318101928785.png)]
[*] 需求一:实现范围过滤
//需求一:查询2021年1月和2月的数据
scan.withStartRow(Bytes.toBytes("202101"));
scan.withStopRow(Bytes.toBytes("202103"));
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kUtwEsEy-1616631335577)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318102604990.png)]
[*] 需求二实现
//需求2:查询2021年的所有数据
Filter prefixFiter = new PrefixFilter(Bytes.toBytes("2021"));
//将过滤器加载到scan中
scan.setFilter(prefixFiter);
[*] 需求三实现
//需求三:查询所有age = 20的数据
/**
* * @param family name of column family
* * @param qualifier name of column qualifier
* * @param op operator
* * @param value value to compare column values against
*/
Filter valueFilter = new SingleColumnValueFilter(
Bytes.toBytes("basic"),//指定列族
Bytes.toBytes("age"),//指定列
CompareOperator.EQUAL,//指定比较器类型
Bytes.toBytes("20")//比较的值
);
//将过滤器加载到scan中
scan.setFilter(valueFilter);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sP5MLfRe-1616631335579)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318104213375.png)]
[*] 需求四实现
//需求4:查询所有数据的name和age这两列
//构建所有需要过滤的列
byte[][] prefixes = {
Bytes.toBytes("name"),
Bytes.toBytes("age")
};
Filter columnFilter = new MultipleColumnPrefixFilter(prefixes);
//将过滤器加载到scan中
scan.setFilter(columnFilter);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vkQbO9w9-1616631335580)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318104930496.png)]
[*] 需求五实现
Filter valueFilter = new SingleColumnValueFilter(
Bytes.toBytes("basic"),//指定列族
Bytes.toBytes("age"),//指定列
CompareOperator.EQUAL,//指定比较器类型
Bytes.toBytes("20")//比较的值
);
//需求4:查询所有数据的name和age这两列
//构建所有需要过滤的列
byte[][] prefixes = {
Bytes.toBytes("name"),
Bytes.toBytes("age")
};
Filter columnFilter = new MultipleColumnPrefixFilter(prefixes);
//需求5:查询所有age = 20的人的name和age
//构建FIlterList
FilterList lists = new FilterList();//MUST_PASS_ALL:and,MUST_PASS_ONE:or
//添加过滤器
lists.addFilter(valueFilter);
lists.addFilter(columnFilter);
//将过滤器加载到scan中
scan.setFilter(lists);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GaXWQJwf-1616631335581)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210318110732471.png)]
[*] 总结
[*]Rowkey范围过滤:StartRow和StopRow
[*]Rowkey前缀过滤:PrefixFilter
[*]Rowkey中列的值的过滤:SingleColumnValueFilter
[*]Rowkey中列的过滤:MultipleColumnPrefixFilter
[*]多种条件的组合过滤:FilterList
知识点09:存储设计:存储架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QFiNIbeF-1616631335582)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210317190105892.png)]
[*] 问题:Hbase整体如何实现数据的存储?
[*] 分析
知识点10:存储设计:Table、Region、RegionServer的关系
https://blog.51cto.com/u_15277063/20210318_%E5%88%86%E5%B8%83%E5%BC%8FNoSQL%E5%88%97%E5%AD%98%E5%82%A8%E6%95%B0%E6%8D%AE%E5%BA%93Hbase%EF%BC%88%E4%B8%89%EF%BC%89.assets/www.myexception.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg
[*] 问题:客户端操作的是表,数据最终存在RegionServer中,表和RegionServer的关系是什么?
[*] 分析
知识点11:存储设计:Region的划分规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xGxSZiF6-1616631335582)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210317191202582.png)]
[*] 问题:一张表划分为多个Region,划分的规则是什么?写一条数据到表中,这条数据会写入哪个Region,分配规则是什么?
[*] 分析
知识点12:存储设计:Region内部存储结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KRgBXSLA-1616631335583)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210317191716413.png)]
[*] 问题:数据在Region的内部是如何存储的?
[*] 分析
知识点13:存储设计:HDFS中的存储结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10viiw3z-1616631335583)(20210318_分布式NoSQL列存储数据库Hbase(三).assets/image-20210317191754182.png)]
[*] 问题:Hbase的数据在HDFS中是如何存储的?
[*] 分析
egionServer的关系
https://blog.51cto.com/u_15277063/20210318_%E5%88%86%E5%B8%83%E5%BC%8FNoSQL%E5%88%97%E5%AD%98%E5%82%A8%E6%95%B0%E6%8D%AE%E5%BA%93Hbase%EF%BC%88%E4%B8%89%EF%BC%89.assets/www.myexception.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg
[*] 问题:客户端操作的是表,数据最终存在RegionServer中,表和RegionServer的关系是什么?
[*] 分析
知识点11:存储设计:Region的划分规则
[外链图片转存中…(img-xGxSZiF6-1616631335582)]
[*] 问题:一张表划分为多个Region,划分的规则是什么?写一条数据到表中,这条数据会写入哪个Region,分配规则是什么?
[*] 分析
知识点12:存储设计:Region内部存储结构
[外链图片转存中…(img-KRgBXSLA-1616631335583)]
[*] 问题:数据在Region的内部是如何存储的?
[*] 分析
知识点13:存储设计:HDFS中的存储结构
[外链图片转存中…(img-10viiw3z-1616631335583)]
[*] 问题:Hbase的数据在HDFS中是如何存储的?
[*] 分析
页:
[1]