HFileV2文件
HFileV2文件写入通过StoreFile.Writer-->HFileWriterV2进行写入。
文件格式通过hfile.format.version配置。默认为2,也只有2这个值在0.96可用。
可通过cf中配置DATA_BLOCK_ENCODING配置dataBlock的encoding,
可配置值:NONE,PREFIX,DIFF,FAST_DIFF,PREFIX_TREE,
通过在family的配置属性中配置BLOCKSIZE,来设置hfile的block大小,默认为65536
通过在family的配置属性中配置BLOOMFILTER,来设置是否启用BLOOMFILTER,默认值为ROW,可选值:NONE,ROW,ROWCOL。
如果io.storefile.bloom.enabled配置的值为true,默认为true.在writer中生成一个全局的bloomfilter的Writer
在StoreFile.Writer中生成的generalBloomFilterWriter,实现类为:CompoundBloomFilterWriter,
bloomfilter的blocksize通过io.storefile.bloom.block.size配置,默认为128*1024(128k)
如果bloomfilter属性不是ROWCOL时,同时io.storefile.delete.family.bloom.enabled配置为true,默认值为true,
在StoreFile.Writer中生成的deleteFamilyBloomFilterWriter,实现类:CompoundBloomFilterWriter
writer.append操作
写HFileV2文件时,在store进行flush时,会生成StoreFile.Writer实例,通过Writer.append写入kv.
public void append(final KeyValue kv) throws IOException {
如果是一个新的kv,也就是row与bloomfilter中的最后一个kv的row不相同,表示需要添加到bloomblock中。
此部分目前是在一个缓冲区中。
appendGeneralBloomfilter(kv);
如果kv是删除的KV,把row添加到deletebloomfilter的block中。
此部分目前是在一个缓冲区中。
appendDeleteFamilyBloomFilter(kv);
通过HFileWriterV2.append写入kv到datablock,
writer.append(kv);
trackTimestamps(kv);
}
HFileWriterV2.append(kv)直接调用如下方法:
private void append(final long memstoreTS, final byte[] key,
final int koffset, final int klength,
finalbyte[] value, finalint voffset, finalint vlength)
throws IOException {
检查key是否合法,首先检查上一个添加的key如果比当前的key大,表示有问题,因为hfile的写入需要排序写入。
如果当前的key比上次写入的key要小,返回值为false,如果返回值为true,表示两个key相同。我指的key是rowkey
boolean dupKey = checkKey(key, koffset, klength);
检查value是否为null,
checkValue(value, voffset, vlength);
如果rowkey与上一次的rowkey不是同一个key时,检查hfile的block是否超过了指定的大小。
如果当前的rowkey与上一次写入的rowkey相同时,
就算是block大小超过了指定的大小,相同的rowkey的kv都会写到一个block中。
if (!dupKey) {
此处是检查fsBlockWriter中的大小是否超过了blocksize的大小,如果起过了。需要执行block的flush操作。
checkBlockBoundary();
}
第一次进行入时,fsBlockWriter的状态为State.INIT;此时需要生成一个新的block,并设置State为State.WRITING;
在执行newBlock操作时,生成一个DataOutputStream,使用一个baosInMemory(ByteArrayOutputStream),
每一个block中,basosInMemory的缓冲区是重用的,因此,每一个block中都会执行baosInMemory.reset操作。
并写入block的header信息。
if (!fsBlockWriter.isWriting())
newBlock();
写入kv到data block的缓冲区中。
// Write length of key and value and then actual key and value bytes.
// Additionally, we may also write down the memstoreTS.
{
DataOutputStream out = fsBlockWriter.getUserDataStream();
out.writeInt(klength);
totalKeyLength += klength;
out.writeInt(vlength);
totalValueLength += vlength;
out.write(key, koffset, klength);
out.write(value, voffset, vlength);
if (this.includeMemstoreTS) {
WritableUtils.writeVLong(out, memstoreTS);
}
}
记录住此block的第一个key,firstkey主要是block index(leaf-level-index)记录每一个block的first key.
// Are we the first key in this block?
if (firstKeyInBlock == null) {
// Copy the key.
firstKeyInBlock = newbyte[klength];
System.arraycopy(key, koffset, firstKeyInBlock, 0, klength);
}
记录最后一个key的值。
lastKeyBuffer = key;
lastKeyOffset = koffset;
lastKeyLength = klength;
entryCount++;
}
flush data block数据刷新
data block的大小默认为65536(64k),当达到此值时,会对block进行flush操作。
在HFileWriterV2中通过append会对block进行检查。
检查是否是新的一个rowkey的值,如果是检查是否需要flush当前的block,并重新创建一个新的block
boolean dupKey = checkKey(key, koffset, klength);
checkValue(value, voffset, vlength);
if (!dupKey) {
checkBlockBoundary();
}
检查是否达到flush的值,并进行flush操作。
private void checkBlockBoundary() throws IOException {
检查block是否达到指定的值。
if (fsBlockWriter.blockSizeWritten() < blockSize)
return;
对datablock进行flush操作,
finishBlock();
写入索引数据到block中。
writeInlineBlocks(false);
生成一个新的block.
newBlock();
}
finishBlock方法:
private void finishBlock() throws IOException {
检查当前的fsBlockWriter的状态非State.WRITING;或者block中的值为0,不做操作。
if (!fsBlockWriter.isWriting() || fsBlockWriter.blockSizeWritten() == 0)
return;
long startTimeNs = System.nanoTime();
// Update the first data block offset for scanning.
if (firstDataBlockOffset == -1) {
如果是第一个block,设置block的offset的值为0,也就是block的开始位置。
firstDataBlockOffset = outputStream.getPos();
}
记录上一个block的偏移量。主要是用来记录block index的一些个准备信息。
此outputStream是每次write一个block后pos的值就会增加。
// Update the last data block offset
lastDataBlockOffset = outputStream.getPos();
设置fsBlockWriter的状态为State.BLOCK_READY;这样就可以重新执行写入操作。
通过读取buffer中的kv的值,通过encoder对block进行操作。如profix_free等。会写入到一个buffer中。
最后把数据写入到HDFS文件中。
fsBlockWriter.writeHeaderAndData(outputStream);
int onDiskSize = fsBlockWriter.getOnDiskSizeWithHeader();
byte[] indexKey = comparator.calcIndexKey(lastKeyOfPreviousBlock, firstKeyInBlock);
把当前block的key与当前block的偏移量,当前block的大小写入到leaf level index(BlockIndex)中。
每一个block就会有一条block的index记录。
dataBlockIndexWriter.addEntry(indexKey, lastDataBlockOffset, onDiskSize);
totalUncompressedBytes += fsBlockWriter.getUncompressedSizeWithHeader();
HFile.offerWriteLatency(System.nanoTime() - startTimeNs);
是否需要写入kv到cache中。如果是需要,写入到readcache中。
if (cacheConf.shouldCacheDataOnWrite()) {
doCacheOnWrite(lastDataBlockOffset);
}
}
DataBlock的格式:
8byte |
4byte |
4byte |
8byte |
1byte |
4byte |
4byte |
... |
blockType |
onDiskSize+checsumSize |
unCompressedSize |
prevOffset |
checksumType |
bytesPerChecksum |
onDiskSize |
data |
BlockType是block类型
第二个是压缩部分下checksumsize的大小
第三部分是未压缩部分的大小
第4部分是上一个block的偏移号
第5部分是checksumtype的类型
第6部分是是每个checksum的字节数,默认为16*1024
第7部分是压缩部分的大小,但不包含checksunsize
最后是数据部分。
写入索引的block数据,要写入的索引包含如下几个:
blockIndex也就是dataBlockIndexWriter的默认实现是HFileBlockIndex.BlockIndexWriter.
BloomFilterIndex,也就是CompoundBloomFilterWriter实现。
DeleteBloomFilterIndex,也就是CompoundBloomFilterWriter实现。
private void writeInlineBlocks(boolean closing) throws IOException {
for (InlineBlockWriter ibw : inlineBlockWriters) {
while (ibw.shouldWriteBlock(closing)) {
long offset = outputStream.getPos();
boolean cacheThisBlock = ibw.getCacheOnWrite();
ibw.writeInlineBlock(fsBlockWriter.startWriting(
ibw.getInlineBlockType()));
fsBlockWriter.writeHeaderAndData(outputStream);
ibw.blockWritten(offset, fsBlockWriter.getOnDiskSizeWithHeader(),
fsBlockWriter.getUncompressedSizeWithoutHeader());
totalUncompressedBytes += fsBlockWriter.getUncompressedSizeWithHeader();
if (cacheThisBlock) {
doCacheOnWrite(offset);
}
}
}
}
1.blockIndex的shouldWriteBlock主要检查大小(非rootindex)是否大于128*1024(128kb),
2.bloomFilterIndex与deleteBloomFilterIndex的 shouldWriteBlock,
只要bloomfilter中有值,也就是chunk中有数据,shouldWriteBlock的方法返回就为true,
把block写入到HDFS中。
blockIndex的blockType为LEAF_INDEX,
bloomfilter的blockType为BLOOM_CHUNK。
也就是说:
blockIndex中记录有每一个dataBlock的firstKey,offset,blockSize,
bloomFilterIndex中记录有每一个(row)rowkey,(rowcol)或者rowkey与Qualifier,的hash值,
此处的hash主要是bloomfilter的相关信息。
每一个dataBlock进行flush后,都会强制flush到bloomfilter的block.
在flush后bloomfilter后,
会在rootBloomFilter(bloomBlockIndexWriter)的缓冲区中记录此bloomfliter的firstkey.offset,blocksize.
在每一个blockindex进行flush后,这个在datablock进行flush时不会强制flsuh,只有达到指定的值时,才进行flush.
在每一次对blockindex进行flush后,会在rootindex的缓冲区中记录住此blockindex的firstkey,offset,blocksize.
最后:
1.在执行writer.close时,写入rootindex的block
如果blockindex的大小超过了128k,会把rootindex的每128k写入一个INTERMEDIATE_INDEX。
记录住所有的INTERMEDIATE_INDEX的firstkey,offset,blocksize,
此处是一个重复的迭代过程,只有当ROOT_INDEX。可以写入的blocksize小于128kb时,把最后一个写入为ROOT_INDEX。
在trailer中记录ROOTINDEX的offset.
2.接下来写入meta,也就是root的bloomfilter的信息。
3.写入FILE_INFO。会在trailer中记录住fileInfo的offset.
4.写入trailer.
Fileinfo中包含:
MAX_SEQ_ID_KEY,记录hfile最大的seqid,
MAJOR_COMPACTION_KEY,是否做过major compaction。
TIMERANGE,记录hfile中的timeRangeTracker.
EARLIEST_PUT_TS,hfile中最老的timestamp
DATA_BLOCK_ENCODING,记录hfile的encoding的配置值
BLOOM_FILTER_TYPE,记录有全局的bloomfilter的类型
DELETE_FAMILY_COUNT,记录有delete的family的个数。
Hfile.LASTKEY,记录此hfile中最后一个key的值,
hfile.AVG_KEY_LEN,记录key的平均长度。
Hfile.AVG_VALUE_LEN,记录value的平均长度。
Trailer中的内容:
majorVersion:hfile的版本号,固定的值2,
minorVersion,hfile的最大版本号,3.
loadOnOpenDataOffset,datablockrootindex的offset
fileInfoOffset,fileinfo的offset,
numDataIndexLevels,rootindex的层级,在上面提到过的INTERMEDIATE_INDEX有几个层级。
UncompressedDataIndexSize,Uncompressedsize总大小。
firstDataBlockOffset,第一个block的offset
lastDataBlockOffset,最后一个block的offset.
ComparatorClassName,比较器的类名称。
dataIndexCount,rootindex中存储的index个数。
.......
相关推荐
Rocky Linux 8.10内核包
内容概要:本文档详细介绍了如何在Simulink中设计一个满足特定规格的音频带ADC(模数转换器)。首先选择了三阶单环多位量化Σ-Δ调制器作为设计方案,因为这种结构能在音频带宽内提供高噪声整形效果,并且多位量化可以降低量化噪声。接着,文档展示了具体的Simulink建模步骤,包括创建模型、添加各个组件如积分器、量化器、DAC反馈以及连接它们。此外,还进行了参数设计与计算,特别是过采样率和信噪比的估算,并引入了动态元件匹配技术来减少DAC的非线性误差。性能验证部分则通过理想和非理想的仿真实验评估了系统的稳定性和各项指标,最终证明所设计的ADC能够达到预期的技术标准。 适用人群:电子工程专业学生、从事数据转换器研究或开发的技术人员。 使用场景及目标:适用于希望深入了解Σ-Δ调制器的工作原理及其在音频带ADC应用中的具体实现方法的人群。目标是掌握如何利用MATLAB/Simulink工具进行复杂电路的设计与仿真。 其他说明:文中提供了详细的Matlab代码片段用于指导读者完成整个设计流程,同时附带了一些辅助函数帮助分析仿真结果。
内容概要:该题库专为研究生入学考试计算机组成原理科目设计,涵盖名校考研真题、经典教材课后习题、章节题库和模拟试题四大核心模块。名校考研真题精选多所知名高校的计算机组成原理科目及计算机联考真题,并提供详尽解析,帮助考生把握考研命题趋势与难度。经典教材课后习题包括白中英《计算机组成原理》(第5版)和唐朔飞《计算机组成原理》(第2版)的全部课后习题解答,这两部教材被众多名校列为考研指定参考书目。章节题库精选代表性考题,注重基础知识与重难点内容,帮助考生全面掌握考试大纲要求的知识点。模拟试题依据历年考研真题命题规律和热门考点,精心编制两套全真模拟试题,并附标准答案,帮助考生检验学习成果,评估应试能力。 适用人群:计划参加研究生入学考试并报考计算机组成原理科目的考生,尤其是需要系统复习和强化训练的学生。 使用场景及目标:①通过研读名校考研真题,考生可以准确把握考研命题趋势与难度,有效评估复习成效;②通过经典教材课后习题的练习,考生可以巩固基础知识,掌握解题技巧;③通过章节题库的系统练习,考生可以全面掌握考试大纲要求的各个知识点,为备考打下坚实基础;④通过模拟试题的测试,考生可以检验学习成果,评估应试能力,为正式考试做好充分准备。 其他说明:该题库不仅提供详细的题目解析,还涵盖了计算机组成原理的各个方面,包括计算机系统概述、数据表示与运算、存储器分层、指令系统、中央处理器、总线系统和输入输出系统等。考生在使用过程中应结合理论学习与实践操作,注重理解与应用,以提高应试能力和专业知识水平。
__UNI__DB9970A__20250328141034.apk.1
rust for minio
国网台区终端最新规范
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
一个简单的机器学习代码示例,使用的是经典的鸢尾花(Iris)数据集,通过 Scikit-learn 库实现了一个简单的分类模型。这个代码可以帮助你入门机器学习中的分类任务。
pyqt离线包,pyqt-tools离线包
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
SQL常用日期和时间函数整理及在sqlserver测试示例 主要包括 1.查询当前日期GETDATE 2.日期时间加减函数DATEADD 3 返回两个日期中指定的日期部分之间的差值DATEDIFF 4.日期格式转换CONVERT(VARCHAR(10),GETDATE(),120) 5.返回指定日期的年份数值 6.返回指定日期的月份数值 7.返回指定日期的天数数值
GSDML-V2.3-Turck-BL20_E_GW_EN-20160524-010300.xml
T_CPCIF 0225-2022 多聚甲醛.docx
《基于YOLOv8的智能仓储货物堆码倾斜预警系统》(包含源码、可视化界面、完整数据集、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计
蚕豆脱壳机设计.zip
台区终端电科院送检文档
Y6一39一No23.6D离心通风机 CAD().zip
django自建博客app
台区终端电科院送检文档