IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 2021SC@SDUSC HBase(九)项目代码分析——数据模型 -> 正文阅读

[大数据]2021SC@SDUSC HBase(九)项目代码分析——数据模型

2021SC@SDUSC

一、简述

HBase是一个KeyValue型的数据库,核心存储结构是KeyValue类,这个类定义了HBase的数据模型,并贯穿了HBase的整个读写链路。同时HBase自身的元数据管理也是使用了业务表相同的模式。

二、数据模型

Table(表格)
一个HBase表格由多行组成
Row(行)
HBase中的行里面包含一个key和一个或者多个包含值的列。行按照行的key字母顺序存储在表格中。因为这个原因,行的key的设计就显得非常重要。数据的存储目标是相近的数据存储到一起。一个常用的行的key的格式是网站域名。
Column(列)
HBase中的列包含用:分隔开的列族和列的限定符。
Column Family(列族)
因为性能的原因,列族物理上包含一组列和它们的值。每一个列族拥有一系列的存储属性,例如值是否缓存在内存中,数据是否要压缩或者他的行key是否要加密等等。表格中的每一行拥有相同的列族,尽管一个给定的行可能没有存储任何数据在一个给定的列族中。
Column Qualifier(列的限定符)
列的限定符是列族中数据的索引。例如给定了一个列族content,那么限定符可能是content:html,也可以是content:pdf。列族在创建表格时是确定的了,但是列的限定符是动态地并且行与行之间的差别也可能是非常大的。
Cell(单元)
单元是由行、列族、列限定符、值和代表值版本的时间戳组成的。
TimeStamp(时间戳)
时间戳是写在值旁边的一个用于区分值的版本的数据。默认情况下,时间戳表示的是当数据写入时RegionSever的时间点,但也可以在写入数据时指定一个不同的时间戳。

三、KeyValue

KeyValue本身就是一串二进制数据,即byte[],通过一些编码规则,将二进制数据映射为六元组或七元组。
KeyValue的byte数组由3部分组成:
1.2个长度字段,每个字段4字节:即key的长度,value的长度
2.key数据
3.value数据
其中,key包括了rowkey,family,qualifier,timestamp,type,这5个部分。
末尾是value字段,其长度由开始的ValueLength字段来定义。最大是Integer#MAX_VALUE,即4GB。

四、表定义和列族定义

HTableDescriptor tableDesc = new HTableDescriptor("test");

日志flush的时候是同步写,还是异步写

tableDesc.setDurability(Durability.SYNC_WAL);
tableDesc.setMemStoreFlushSize(256*1024*1024);
HColumnDescriptor colDesc = new HColumnDescriptor("f");

块缓存,保存着每个HFile数据块的startKey

colDesc.setBlockCacheEnabled(true);
colDesc.setBlocksize(64*1024);

bloom过滤器,有ROW和ROWCOL,ROWCOL除了过滤ROW还要过滤列族

colDesc.setBloomFilterType(BloomType.ROW);

写的时候缓存bloom并缓存索引

colDesc.setCacheBloomsOnWrite(true);
colDesc.setCacheIndexesOnWrite(true);  

存储和进行compaction的时候使用压缩算法

colDesc.setCompressionType(Algorithm.SNAPPY);
colDesc.setCompactionCompressionType(Algorithm.SNAPPY);
colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX);

写入硬盘的时候是否进行编码;关闭的时候,是否剔除缓存的块;是否保存那些已经删除掉的kv;让数据块缓存在LRU缓存里面有更高的优先级

colDesc.setEncodeOnDisk(true);
colDesc.setEvictBlocksOnClose(true);
colDesc.setKeepDeletedCells(false);
colDesc.setInMemory(true);
colDesc.setMaxVersions(3);
colDesc.setMinVersions(1);

集群间复制的时候,如果被设置成REPLICATION_SCOPE_LOCAL就不能被复制了

colDesc.setScope(HConstants.REPLICATION_SCOPE_GLOBAL);
colDesc.setTimeToLive(18000);
tableDesc.addFamily(colDesc);

bloom过滤器,过滤加速colDesc.setBloomFilterType(BloomType.ROW),colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX);压缩内存和存储中的数据,内存紧张时设置 
colDesc.setInMemory(true);让数据块缓存在LRU缓存里面有更高的优先级 
KeyValue的存储:

public void write(Cell cell) throws IOException {
checkFlushed();
write(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
write(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
write(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
this.out.write(Bytes.toBytes(cell.getTimestamp()));
this.out.write(cell.getTypeByte());
write(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
}

分别定义了Row rowkey的起始位置、长度;Column family 列族的起始位置、长度;Qualifier 列名的起始位置、长度;Version 时间戳;Value 值的起始位置、长度

五、使用KeyValue

如果通过KeyValue的接口来获取KeyValue内部的各个字段的数据,那么,从KeyValue中获取任何一个字段的数据,本质上都是从这个byte[]中截取一段,然后返回。这必然涉及到两种数据获取方式:
拷贝一次:如KeyValue#getRow(), getValue()等方法,创建一个新的byte[],将内部的byte[]中对应的字段的二进制拷贝到新的数组中,然后返回新的数组
返回ptr:即返回一个3元组,(byte[], offset, length),让用户自己根据offset来在一个byte[]定位起始位置,读取指定长度的数据,即可得到需要的字段的内容(参见Cell接口的定义)。KeyValue为每个字段提供了3个接口来实现这个功能,这里以Value为例:

  • getValueArray():返回一个byte[],这个数组中存储了value
  • getValueOffset():返回一个int,指示value字段的起始的字节偏移量
  • getValueLength():返回一个int,指示value字段的实际长度,单位是字节

六、总结

列存储的话存储的时候每个列都会重复前面的rowkey、列族这些信息,在列很多的情况下,rowkey和列族越长,消耗的内存和列族都会很大,所以它们都要尽量的短。
可以用colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX_TREE)来压缩一下内存中的大小,这个后面后面会讲到

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-11-15 15:56:05  更:2021-11-15 15:58:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:27:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码