HBase	
  Source	
  Code	
  Analysis	
  	
  
1.  HFile
2.  HBase Compact
3.  HBase Split
基于HBase0.96
FX__Bull -- 移动数据组
·正⽂文级别1 	
·HFIle 是什么? 
	
·⽤用来解决什么问题?
  ·正⽂文级别2	
	
  ·正⽂文级别3	
  ·⾃自⼰己设计怎么实现?
	
   ·正⽂文级别4	
   ·HFile如何做的?
	
    ·正⽂文级别5 	
 ...
HFile是什么
一种文件格式	
  
•  	
   采用SStable的思想,HBase的底层存储是HFile;	
  
•  	
   存储的基本数据是key-­‐value对	
  
	
  
	
  
	
  
与HDFS天然集成	
...
⽤用来解决什么问题
要解决的问题就是:
1.  以何种方式将按照Key排好序的KeyValue数据存储
到磁盘,以便高效的操作数据:low-latency
reads and writes。
2.  HFile的依赖的分布式文件系统是HDFS,...
⾃自⼰己如何设计?
1、首先检索排好序的数据首先会想到?	
  
	
  
2、HFile可能会包含上亿条数据如何做?	
  
	
  
3、为什么不用B-­‐Tree	
  
	
  
	
  
	
  
	
  
	
  
	
  
	
 ...
HFile如何实现的
1、分块 + 分级索引	
  
	
  
2、布隆过滤器过滤掉集合中不存在的Key	
  
	
  
3、⽂文件存磁盘,需记录索引的位置等信息	
  
HFile如何实现的
分析文件格式最好的方法,其实就是看他源码的读和写过
程;	
  
分析HBase向磁盘写了什么内容,便可以分析出格式;	
  
	
  

HBase	
  write	
  path	
  
HFile如何实现的
实现写HFile首先需要构建一个HFile.Writer对象。	
  
	
  
跟踪KeyValue对象的创建过程和HFileWriterV2对象的
append(KeyValue	
  kv	
  )方法,构造出每个R...
HFile如何实现的
随着不断地加入新的KeyValue对,当DataBlock达到一定的阀
值时(fsBlockWriter.blockSizeWritten() < blockSize),会
执行finishBlock()操作
1、按照指定...
HFile如何实现的
HFile如何实现的
当索引的达到一定阀值时(默认HFileBlockIndex.DEFAULT_MAX_CHUNK_SIZE
128KB),会在写一个LEAF_INDEX。
HFile如何实现的
当写完之后,调用write的close方法,首先执行finishBlock()将剩余的数据加入
输出流,并写InlineBlockIndex等;
顺序添加metadata、rootIndex、metaBlockIndex、...
HFile如何实现的
HFile的fix_trailer 包含了指向其它块的offsets信息,各个模块的内容:
执行 bin/hbase org.apache.hadoop.hbase.io.hfie.HFile -m -f /opt/loc...
HFile如何实现的
到此为止写过程结束:	
  
	
  
	
  
详细内容请看,欢迎交流:
hVp://wiki.sankuai.com/pages/viewpage.acYon?pageId=78479497	
  
	
  
	
  ...
HFile如何实现的
相对于HFileV1:	
  
	
  
1、写过程索引以及布隆过滤器不用一直保存在内存里,当达到阀值变
写到磁盘,同样由于分级读过程不需要将所有索引在启动时便加载到内
存,降低内存使用和启动时间,思路都是将它们切分为多个...
HFile如何实现的
那么读该如何实现?
1、创建HFile.Reader时,加载Trailer,进而加载FileInfo,RootIndex等内
容。
2、查找的过程实质上就是对各级索引进行二分查找,并根据BlockType来判断
块是索引还...
HFile⼀一些性能点
1、大的块适合顺序扫描,但是随机读写性能降低,(大的快解压速
度会变慢),小的HFile block更加适合随机读写,但是需要更多地
内存来存放index.
2、将块加到cache,默认策略为LRU,对GC不太友好。
/...
HBase Compact

·正⽂文级别1 	
	
·概述 
 ·正⽂文级别2	
 	
·触发条件
  ·正⽂文级别3	
	
  ·如何选择
   ·正⽂文级别4	
	
•  如何合并
    ·正⽂文级别5
HBase Compact
•  HBase stores rows of data in tables. Tables are split into chunks
of rows called “regions”. Those regions...
HBase Compact
HBase Compact
HBase	
  bulk-­‐load	
  就是先根据region分区等条件,先生成
storeFile,之后mv到相应的store目录下,及时生效的	
  
	
  
HBase Compact
对于HBase,执行一个写操作时,首先会将内容写到内存中的
MemStore,当MemStore达到一定阀值时,这个MemStore就会冻结,同
时产生一个新的MemStore来响应写操作,之前的MemSore会f...
HBase Compact
	

There are two types of compactions: minor and major. 	

	



	

Minor compactions will usually pick up a...
HBase Compact
主要入口:	
  
	
  
HregionServer启动时,会启动一个任务,定期扫描RegionServer托管
的所有Hregion下面的所有store,检查是否需要进行compact.
在不做配置的情况下10...
HBase Compact
HStore中StoreFIles的个数	
  –	
  正在执⾏行CompacYng的文件个数	
  >	
  
minFilesToCompact	
  
org.apache.hadoop.hbase.regi...
HBase Compact
如果符合条件,则由CompactSplitThread.requestSystemCompaction发起
compact请求;
接着:
1、selectCompaction(r, s, priority, requ...
HBase Compact
select StoreFileToCompct:
1.  选出待执行Compact的storefiles。由于在Store中的文件可能已经在进行Compacting,因此,
这里取出未执行Compacting的文件...
HBase Compact
合并过程:
1、根据StoreFileScanner 列表等参数,创建InternalScanner (这是一个
StoreScanner)
2、生成StoreFile.Writer 负责向 ./tmp目录下写新的S...
HBase Compact
一些配置参数	
  
HBase Compact
总结:
HBase的合并操作其实就是扫描各个StoreFile并将其写入一个较大的文件,
之后用这个大的StoreFile文件替换到之前的多个小文件。
1、在实际使用过程中,通常会禁用major Compact,在集...
HBase Split
Why	
  Hbase	
  needs	
  split?	
  
	
  
A table typically consists of many regions, which are in turn
hosted...
HBase Split
入口:
compactSplitThread.requestSplit(region)

HBase Split
判断是否分裂主要通过RegionSplitPolicy接口:其实现有ConstantSizeRegionSplitPolicy,
IncreasingToUpperBoundRegionSplitPolicy, KeyP...
HBase Split
总体步骤:
SplitTransaction.execute,真正进行split的代码:
第一步:createDaughters,
第二步:openDaughters,
第三步: transitionZKNode。

HBase Split
create	
  daughter	
  
	
  

1、创建znode节点,/hbase/region-­‐in-­‐transiYon/region-­‐name	
  	
  
	
  
2、因为HMater...
HBase Split
open	
  daughter	
  
	
  
	
   
1、向.meta.表发起写请求,标注parent	
  region已经下线	
  
	
  
2、初始化daughter	
  region	
  
	...
HBase Split
transiYonZKNode	
  
	
  

1、修改zookeeper	
  /hbase/region-­‐in-­‐transiYon/region-­‐name/SPLIT	
  ,Hmaster分
派d...
HBase Split

HBase Split
一些经验:
•  根据使用场景采取不同的分裂策略:如果我们知道key的分布,可以采用预分
区,并采用ConstantSizeRegionSplitPolicy分裂策略,并将分裂条件罚值设
的大些如果不知道key的分布,就...
Thanks
Upcoming SlideShare
Loading in …5
×

HFile,Compact And Split of HBase

1,479 views

Published on

Published in: Technology, Art & Photos
2 Comments
5 Likes
Statistics
Notes
No Downloads
Views
Total views
1,479
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
29
Comments
2
Likes
5
Embeds 0
No embeds

No notes for slide

HFile,Compact And Split of HBase

  1. 1. HBase  Source  Code  Analysis     1.  HFile 2.  HBase Compact 3.  HBase Split 基于HBase0.96 FX__Bull -- 移动数据组
  2. 2. ·正⽂文级别1  ·HFIle 是什么?  ·⽤用来解决什么问题?   ·正⽂文级别2   ·正⽂文级别3   ·⾃自⼰己设计怎么实现?    ·正⽂文级别4    ·HFile如何做的?     ·正⽂文级别5     ·HFile有何优缺点?
  3. 3. HFile是什么 一种文件格式   •    采用SStable的思想,HBase的底层存储是HFile;   •    存储的基本数据是key-­‐value对         与HDFS天然集成                    
  4. 4. ⽤用来解决什么问题 要解决的问题就是: 1.  以何种方式将按照Key排好序的KeyValue数据存储 到磁盘,以便高效的操作数据:low-latency reads and writes。 2.  HFile的依赖的分布式文件系统是HDFS,决定了写 HFile也只能采用append操作实现,一旦写入数据 便是immutable的,我们不能对特定的key进行编 辑、删除等操作。 HFile文件格式对特定字节存储什么内容做了规定,以便 可以按照格式读取数据。
  5. 5. ⾃自⼰己如何设计? 1、首先检索排好序的数据首先会想到?     2、HFile可能会包含上亿条数据如何做?     3、为什么不用B-­‐Tree                  
  6. 6. HFile如何实现的 1、分块 + 分级索引     2、布隆过滤器过滤掉集合中不存在的Key     3、⽂文件存磁盘,需记录索引的位置等信息  
  7. 7. HFile如何实现的 分析文件格式最好的方法,其实就是看他源码的读和写过 程;   分析HBase向磁盘写了什么内容,便可以分析出格式;     HBase  write  path  
  8. 8. HFile如何实现的 实现写HFile首先需要构建一个HFile.Writer对象。     跟踪KeyValue对象的创建过程和HFileWriterV2对象的 append(KeyValue  kv  )方法,构造出每个Record的格 式:   key=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaZI/info:city/LATEST_TIMESTAMP/Put  
  9. 9. HFile如何实现的 随着不断地加入新的KeyValue对,当DataBlock达到一定的阀 值时(fsBlockWriter.blockSizeWritten() < blockSize),会 执行finishBlock()操作 1、按照指定压缩方式,对DataBlock(KeyValue部分)进行压缩。 2、进行组装Header,添加循环冗余校验信息等操作 3、添加一条索引记录,将这个块的 firstKey,lastDataBlockOffset,onDiskDataSize加入LEAF_INDEX索 引项。 备注:索大小大概为(56+AvgKeySize)*NumBlocks 假如BlockSize为64K ,假如HFile大小达到100G,那么索引将近 200M
  10. 10. HFile如何实现的
  11. 11. HFile如何实现的 当索引的达到一定阀值时(默认HFileBlockIndex.DEFAULT_MAX_CHUNK_SIZE 128KB),会在写一个LEAF_INDEX。
  12. 12. HFile如何实现的 当写完之后,调用write的close方法,首先执行finishBlock()将剩余的数据加入 输出流,并写InlineBlockIndex等; 顺序添加metadata、rootIndex、metaBlockIndex、FileInfo、Trailer等信息。 ROOT_INDEX: 1.  添加ROOT_INDEX对这个InlineBlockIndex的索引项。 2.  发现如果root_index的size达到一定阀值(128K),便会加一级索引,达 到3级
  13. 13. HFile如何实现的 HFile的fix_trailer 包含了指向其它块的offsets信息,各个模块的内容: 执行 bin/hbase org.apache.hadoop.hbase.io.hfie.HFile -m -f /opt/local/ hbase/uuid_rtgeo/06faaf5e0ea384d277061bf00757710e/info/ a596111cbc8f4e1b96da230fd588f8a5
  14. 14. HFile如何实现的 到此为止写过程结束:       详细内容请看,欢迎交流: hVp://wiki.sankuai.com/pages/viewpage.acYon?pageId=78479497       阅读HBase代码时maven依赖hadoop源码无法查看 解决办法: 1、下载hadoop-1.1.2.tar.gz 2、找到其源码包,打包jar,buildpath添加、刷新即可            
  15. 15. HFile如何实现的 相对于HFileV1:     1、写过程索引以及布隆过滤器不用一直保存在内存里,当达到阀值变 写到磁盘,同样由于分级读过程不需要将所有索引在启动时便加载到内 存,降低内存使用和启动时间,思路都是将它们切分为多个block.   2、对压缩数据的支持,记录compressed size可以在扫描HFile时不用 解压,不用查找索引,直接skip过当前块进入下一块。 V1:   hVp://wiki.sankuai.com/download/aVachments/78479497/ image2013-­‐12-­‐9%2014%3A43%3A27.png? version=1&modificaYonDate=1386571406000&api=v2        
  16. 16. HFile如何实现的 那么读该如何实现? 1、创建HFile.Reader时,加载Trailer,进而加载FileInfo,RootIndex等内 容。 2、查找的过程实质上就是对各级索引进行二分查找,并根据BlockType来判断 块是索引还是Data已决定是否需要继续向下寻找。 3、load块,然后顺序扫描,seek到指定位置。
  17. 17. HFile⼀一些性能点 1、大的块适合顺序扫描,但是随机读写性能降低,(大的快解压速 度会变慢),小的HFile block更加适合随机读写,但是需要更多地 内存来存放index. 2、将块加到cache,默认策略为LRU,对GC不太友好。 //TODO bucketCache 3、HFileV2的分级索引,虽然可以减少内存的使用量,加快启动速 度,但是多了1-2次IO,尤其是HFile文件较大时,随机读很可能比 V1要多2次IO操作,进而读取速度变慢。
  18. 18. HBase Compact ·正⽂文级别1  ·概述   ·正⽂文级别2   ·触发条件   ·正⽂文级别3   ·如何选择    ·正⽂文级别4 •  如何合并     ·正⽂文级别5
  19. 19. HBase Compact •  HBase stores rows of data in tables. Tables are split into chunks of rows called “regions”. Those regions are distributed across the cluster, hosted and made available to client processes by the RegionServer process. •  A region is a continuous range within the key space, meaning all rows in the table that sort between the region’s start key and end key are stored in the same region. a single row key belongs to exactly one region at any point in time •  A Region in turn, consists of many “Stores”, which correspond to column families. A store contains one memstore and zero or more store files. The data for each column family is stored and accessed separately. 
  20. 20. HBase Compact
  21. 21. HBase Compact HBase  bulk-­‐load  就是先根据region分区等条件,先生成 storeFile,之后mv到相应的store目录下,及时生效的    
  22. 22. HBase Compact 对于HBase,执行一个写操作时,首先会将内容写到内存中的 MemStore,当MemStore达到一定阀值时,这个MemStore就会冻结,同 时产生一个新的MemStore来响应写操作,之前的MemSore会flush到 磁盘,形成一个StoreFile文件。 随着MemStore不断地向磁盘flush StoreFile文件,会对读性能造 成影响,导致性能变慢,因为每个读操作都需要打开所有的 StoreFile文件,并且合并查询,compact做的操作就是将多个文件中 的内容合并,是Famliy上的操作。
  23. 23. HBase Compact There are two types of compactions: minor and major.  Minor compactions will usually pick up a couple of the smaller adjacent StoreFiles and rewrite them as one. Minors do not drop deletes or expired cells, only major compactions do this. Sometimes a minor compaction will pick up all the StoreFiles in the Store and in this case it actually promotes itself to being a major compaction.
  24. 24. HBase Compact 主要入口:     HregionServer启动时,会启动一个任务,定期扫描RegionServer托管 的所有Hregion下面的所有store,检查是否需要进行compact. 在不做配置的情况下10000s,大概3个小时左右check一次。 see : org.apache.hadoop.hbase.regionserver.CompactionChecker;
  25. 25. HBase Compact HStore中StoreFIles的个数  –  正在执⾏行CompacYng的文件个数  >   minFilesToCompact   org.apache.hadoop.hbase.regionserver.compacYons.RaYoBasedCompacYonPolicy     minor  CompacYon条件   判断是否需要major_compact  :public  boolean  isMajorCompacYon(final   CollecYon<StoreFile>  filesToCompact)  
  26. 26. HBase Compact 如果符合条件,则由CompactSplitThread.requestSystemCompaction发起 compact请求; 接着: 1、selectCompaction(r, s, priority, request),选取需要合并的 StoreFile文件列表,作为compact候选者.<到最后过小于最小数,则 结束,大于最大数则取其子集进行compact> 2、pool.execute(new CompactionRunner(s, r, compaction, pool)), 执行compact
  27. 27. HBase Compact select StoreFileToCompct: 1.  选出待执行Compact的storefiles。由于在Store中的文件可能已经在进行Compacting,因此, 这里取出未执行Compacting的文件,将其加入到Candidates中。 2.  执行compactSelection,在Candidates中选出需要进行compact的文件,并封装成 CompactSelection对象当中。 •  •  选出过期的store files 过滤对于大文件进行Compaction操作。判断fileToCompact队列中的文件是否超过了 maxCompactSize,如果超过,则过滤掉该文件,避免对于大文件进行compaction。 •  判断是否需要进行major_compact,判断上次进行majorCompaction到当前的时间间隔, 如果超过设置值等。 •  如果不是major 则执行下面算法,筛选出需要合并的StoreFile; -----http://hbase.apache.org/book/regions.arch.html#compaction,这样做使 得Compaction尽可能工作在最近刷入hdfs的小文件的合并,从而使得提高Compaction的执行 效率。
  28. 28. HBase Compact 合并过程: 1、根据StoreFileScanner 列表等参数,创建InternalScanner (这是一个 StoreScanner) 2、生成StoreFile.Writer 负责向 ./tmp目录下写新的StoreFile. 3、performCompaction(scanner, writer, smallestReadPoint) 执行合并 操作,将数据写到./tmp,关闭writer,生成新生成的StoreFile。 4、moveCompatedFilesIntoPlace(cr, newFiles);移动到相应Store的目录 下 5、删掉旧的 StoreFiles .this.fs.removeStoreFiles(this.getColumnFamilyName(), compactedFiles) 备注:StoreScanner的next方法会ScanQueryMatcher.MatchCode qcode = matcher.match(kv);过滤掉一些不符合要求的KeyValue,比如Major的 delete等
  29. 29. HBase Compact 一些配置参数  
  30. 30. HBase Compact 总结: HBase的合并操作其实就是扫描各个StoreFile并将其写入一个较大的文件, 之后用这个大的StoreFile文件替换到之前的多个小文件。 1、在实际使用过程中,通常会禁用major Compact,在集群压力小的时候, 定时天/周/月 进行compact操作 2、合并过程不影响读写服务。 3、根据应用的需求设置ttl,并且设置minVersions=0,根据 selectCompation优选清理过期不保留版本的文件的策略,这样会使得这部 分数据在CompactionChecker的周期内被清理。 http://wiki.sankuai.com/pages/viewpage.action?pageId=77466463
  31. 31. HBase Split Why  Hbase  needs  split?     A table typically consists of many regions, which are in turn hosted by many region servers. Thus, regions are the physical mechanism used to distribute the write and query load across region servers. When a table is first created, HBase, by default, will allocate only one region for the table. This means that initially, all requests will go to a single region server, regardless of the number of region servers. This is the primary reason why initial phases of loading data into an empty table cannot utilize the whole capacity of the cluster. 实现较为复杂,涉及到旧Region下线,以及新的Region上 线。 
  32. 32. HBase Split 入口: compactSplitThread.requestSplit(region) 
  33. 33. HBase Split 判断是否分裂主要通过RegionSplitPolicy接口:其实现有ConstantSizeRegionSplitPolicy, IncreasingToUpperBoundRegionSplitPolicy, KeyPrefixRegionSplitPolicy •  0.94之前版本默认分裂策略为ConstantSizeRegionSplitPolicy,只是简单的判断下 store.getSize() > desiredMaxFileSize ,可以通过“hbase.hregion.max.filesize"进行 配置,default10GB •  0.94之后默认的为IncreasingToUpperBoundRegionSplitPolicy,判断策略: Min (R^2 * “hbase.hregion.memstore.flush.size”, “hbase.hregion.max.filesize”),R代表当前 table在这个regionserver上面所有在线的region的个数。假如 memStoreSize 为128M,则第 一次split为128M,之后 512MB, 1152MB, 2GB, 3.2GB, 4.6GB, 6.2GB, etc. 当第9次分裂之 后,大小增大到10G之后,则达到10G进行分裂。所以分裂时机和这个hregionServer负责的 region的个数有很大关系。 •  splitKey均为midKey,通过DataBlockIndex获取 •  如果我们能大体遇见key的分布,并且不希望表经常分裂,可以建表时分裂策略采用 ConstantSizeRegionSplitPolicy,并且设置hbase.hregion.max.filesize为一个很大的值。
  34. 34. HBase Split 总体步骤: SplitTransaction.execute,真正进行split的代码: 第一步:createDaughters, 第二步:openDaughters, 第三步: transitionZKNode。 
  35. 35. HBase Split create  daughter      1、创建znode节点,/hbase/region-­‐in-­‐transiYon/region-­‐name       2、因为HMater是 /hbase/region-­‐in-­‐transiYon的观察值,进而更新这个 region的信息。     3、RegionServer在当前region目录下创建.splits/子目录     4、HRegionServer  close  ParentHRegion,同时将MemStore里的数据Flush到磁 盘,此时client对这个Region的读取和写入操作已经得不到响应了,     5、生成daughter  A 和 B 的Reference  ,并存放在 .splits/ [daughter]_EncodedName/familyName/storefileName.RegionEncodedName下, 分别指向parent的上半部分和下半部分。     6、创建真正的region目录,并将生成的A和B  Reference文件拷贝到相应目录 下,ef文件移动到正常目录下,参考HReionFileSystem  以下方法,其实就是 一个mv操作。  
  36. 36. HBase Split open  daughter        1、向.meta.表发起写请求,标注parent  region已经下线     2、初始化daughter  region     3、daughter的信息写入.meta.表。  
  37. 37. HBase Split transiYonZKNode      1、修改zookeeper  /hbase/region-­‐in-­‐transiYon/region-­‐name/SPLIT  ,Hmaster分 派daughter  region,进行负载均衡等。       2、对Reference文件执行compact操作,形成真正的HFile,  
  38. 38. HBase Split 
  39. 39. HBase Split 一些经验: •  根据使用场景采取不同的分裂策略:如果我们知道key的分布,可以采用预分 区,并采用ConstantSizeRegionSplitPolicy分裂策略,并将分裂条件罚值设 的大些如果不知道key的分布,就采用 IncreasingToUpperBoundRegionSplitPolicy,且不采用预分区,开始只生成 一个region,然后让其自行分裂。 •  禁用split,将region大小设置成较大值,参考值100G 
  40. 40. Thanks

×