HBase HFile与Prefix Compression内部实现全解--KeyValue格式
目前存在两种版本的HFile: HFile V1和HFile V2
HBase 0.92之前的版本仅支持HFile V1,
HBase 0.92/0.94同时支持HFile V1和HFile V2。
本文将说明KeyValue到底是什么以及当KeyValue越来越多时出现大量类似的数据有哪些算法能减少重复?
首先来看一个例子:
假设需要将用户的基本信息以及正在参与的开源项目的有关信息存入HBase:
- 用户基本信息 参与的开源项目
- ——————— —————————-
- 用户Id 职业 性别 tomcat hbase
- ——————— —————————-
- zhh2009 码农 男 提patch打酱油 提patch打酱油
- 用户Id 职业 性别 tomcat ant
- ——————— —————————-
- jdd1999 码神 男 创始人 创始人
- ———————————————————
- 表1.1
用户Id 职业 性别 tomcat hbase
zhh2009 码农 男 提patch打酱油 提patch打酱油
用户Id 职业 性别 tomcat ant
jdd1999 码神 男 创始人 创始人
从这个例子来看,用户的基本信息比较好确定,但是参与的开源项目不确定且在开源项目中扮演的角色也不确定,
所以用关系数据库不太好建表,因为不知道具体有多少列,也无法把相关的列归成一个组。
1.1 列族
HBase是一种基于列的数据库,相关的列可以归到一个列族(Column Family),
每个列族中具体有哪些列不必事先知道,可以在需要的时候添加,比如在用户基本信息中为zhh2009加入email这样的列,
上例中”用户基本信息”和”参与的开源项目”可以作为两个列族,
不同的列族在HBase内部通常对应一个目录,这样不同的列值只会放到它所属的列族目录下。
1.2 rowKey
我们希望通过查询某个列就能把同一个列族或多个列族中的信息取出来,用户Id就是这样的列,
比如当我们要查询zhh2009的邮箱和参与的开源项目时,根据用户Id来查就不会查到jdd1999的信息,
在HBase中称这样的列为rowKey。
HBase是如何存放上例中的信息呢?
将用户Id这一列抽出来作为rowKey, 把上面的信息按如下格式扁平化:
<rowKey, 列族名称, 列名 => 列值> —————————————————– <zhh2009, 用户基本信息, 职业 => 码农> <zhh2009, 用户基本信息, 性别 => 男> <zhh2009, 参与的开源项目, tomcat => 提patch打酱油> <zhh2009, 参与的开源项目, hbase => 提patch打酱油> <jdd1999, 用户基本信息, 职业 => 码神> <jdd1999, 用户基本信息, 性别 => 男> <jdd1999, 参与的开源项目, tomcat => 创始人> <jdd1999, 参与的开源项目, ant => 创始人> —————————————————– 表1.2
<zhh2009, 用户基本信息, 职业 => 码农>
<zhh2009, 用户基本信息, 性别 => 男>
<zhh2009, 参与的开源项目, tomcat => 提patch打酱油>
<zhh2009, 参与的开源项目, hbase => 提patch打酱油>
<jdd1999, 用户基本信息, 职业 => 码神>
<jdd1999, 用户基本信息, 性别 => 男>
<jdd1999, 参与的开源项目, tomcat => 创始人>
<jdd1999, 参与的开源项目, ant => 创始人>
表1.2中的每一行在HBase中对应一个KeyValue,
“=>”左边的是KeyValue中的”Key”,”=>”右边对应KeyValue中的”Value”。
当然这只是KeyValue的一个简化格式,内部格式并非那么简单,我们接下来看看真实的KeyValue是怎样的?
2. KeyValue内部格式
KeyValue内部格式可以分成三部份: 头、Key、Value,如表2.1所示
名称 字节数 说明 ——————————————————————– keyLength 4 表示Key所占的总字节数 valueLength 4 表示Value所占的总字节数 rowKeyLength 2 表示rowKey所占的字节数 rowKey rowKeyLength rowKey columnFamilyLength 1 表示列族名称所占的字节数 columnFamily columnFamilyLength 列族名称 columnName columnNameLength 列名 timestamp 8 时间戳 type 1 Key类型,比如是新增(Put),还是删除(Delete) value valueLength 列值 ——————————————————————– 表2.1
keyLength 4 表示Key所占的总字节数
valueLength 4 表示Value所占的总字节数
rowKeyLength 2 表示rowKey所占的字节数
rowKey rowKeyLength rowKey
columnFamilyLength 1 表示列族名称所占的字节数
columnFamily columnFamilyLength 列族名称
columnName columnNameLength 列名
timestamp 8 时间戳
type 1 Key类型,比如是新增(Put),还是删除(Delete)
value valueLength 列值
keyLength和valueLength组成头部,
rowKeyLength到type这7项组成Key,最后一项value代表第三部份: Value,
上面有个地方值得注意,在columnFamily前面有columnFamilyLength,
但是在columnName之前并没有columnNameLength这一项,为了节省空间,这不是必需的,
当在解析KeyValue时,通过keyLength-8(timestamp)-1(type)就可以确定columnName在此KeyValue中的结束位置。
把表1.2中的前两行按表2.1中的格式生成两个KeyValue:
KeyValue A 代表: <zhh2009, 用户基本信息, 职业 => 码农>
KeyValue B 代表: <zhh2009, 用户基本信息, 性别 => 男>
名称 字节数 KeyValue A KeyValue B —————————————————————————- keyLength 4 35 35 valueLength 4 4 2 rowKeyLength 2 7 7 rowKey rowKeyLength zhh2009 zhh2009 columnFamilyLength 1 12 12 columnFamily columnFamilyLength 用户基本信息 用户基本信息 columnName columnNameLength 职业 性别 timestamp 8 1329663787364 1329663787364 type 1 4(Put) 4(Put) value valueLength 码农 男 —————————————————————————- 表2.2
keyLength 4 35 35
valueLength 4 4 2
rowKeyLength 2 7 7
rowKey rowKeyLength zhh2009 zhh2009
columnFamilyLength 1 12 12
columnFamily columnFamilyLength 用户%E
相关文章
- Elasticsearch集群部署(Linux || Windows)
- Centos7 最小化安装使用到的包
- HM5166原厂13V,10A全集成同步升压转换器IC
- Linux修改系统时间
- Kibana查询语言(KQL)AND、OR匹配,模糊匹配
- Spring自带工具类(断言、ObjectUtils、FileCopyUtils、ResourceUtils、StreamUtils、ReflectionUtils、AopUtils、AopCont)
- R绘图|基因表达水平分布图绘制
- fig,ax = plt.subplots()
- PL2628 SOT23-6 1.2MHz恒定频率电流模式升压转换器 泛海微电子代理商
- Centos7.x 防火墙
- R包|用SCI文章的配色画图
- R绘图|ggplot自定义主题一包搞定
- 隧道代理如何测试访问网站的响应时间?
- 让化学分子动起来——MolView
- R语言中的特殊值及缺失值NA的处理方法
- 解密Prompt系列2. 冻结Prompt微调LM: T5 & PET & LM-BFF
- 解密Prompt系列1. Tunning-Free Prompt:GPT2 & GPT3 & LAMA & AutoPrompt
- 小样本利器5. 半监督集各家所长:MixMatch,MixText,UDA,FixMatch
- 聊聊损失函数1. 噪声鲁棒损失函数简析 & 代码实现
- NLP手札1. 金融信息负面及主体判定方案梳理&代码实现