2019-02-21
架构
主从架构,HMaster负责分配region,DDL操作,读写经由regionserver直接和datanode交互,数据文件全部存储在HDFS上
Region,一个table由rowkey被划分成多个region,一个region包含了从startkey到endkey范围内的所有整行,一个region包含多个store
Store,每个columnfamily对应一个store,每个store包含多个storefile和一个memstore
Memstore,region的写缓存。保存还未写入HFile的数据,写入数据前会先做排序,每个region每个CF都会拥有一个Memstore,这就是为什么CF不能建太多的原因。
Meta表,存储了region的位置信息,保存在zookeeper中
rowkey
http://smartsi.club/introduction-to-hbase-rowkey-design.html
- 越高频的查询字段排列越靠左
- 按照 RowKey 来分散到不同 Region,不合理的 RowKey 设计会导致热点问题。热点问题是大量的 Client 直接访问集群的一个或极少数个节点,而集群中的其他节点却处于相对空闲状态
- 散列原则:设计的 RowKey 应均匀的分布在各个 Region 上。避免递增,否则读写负载都会集中在某个热点 Region,降低性能,甚至引起 RegionServer 过载。
rowkey设计如果避免热点
- 加盐,由于分配是随机的,因此如果我们想要以字典序取回数据,我们需要做更多的工作。加盐增加了写入吞吐量,但会增加读取的成本。
- 哈希,使用哈希来代替加盐,这样会使得 RowKey 始终有可预测前缀(对于每一个 RowKey 都有确定性的前缀)。通过哈希我们可以知道前缀进而检索该行数据。我们还可以做一些优化,例如使某些键始终位于同一 Region。
- 翻转RowKey,可以有效的使 RowKey 随机分布,但是牺牲了 RowKey 的有序性特性。
- 分桶时间戳方法, long bucket = timestamp % numBuckets;
- 如果我们经常访问最新事件,那么将时间戳存储为反向时间戳(例如,Long.MAX_VALUE – timestamp)
region split
loadbalancer
priority queue
LSM树
link
link
link
link
link
compaction
HFile
以下内容来自于同事分享
起初,HFile中并没有任何Block,数据还存在于MemStore中。
Flush发生时,创建HFile Writer,第一个空的Data Block出现,初始化后的Data Block中为Header部分预留了空间,Header部分用来存放一个Data Block的元数据信息。
而后,位于MemStore中的KeyValues被一个个append到位于内存中的第一个Data Block中:
当Data Block增长到预设大小(默认64KB)后,一个Data Block被停止写入,该Data Block将经历如下一系列处理流程:
1. 如果有配置启用压缩或加密特性,对Data Block的数据按相应的算法进行压缩和加密。
2.在预留的Header区,写入该Data Block的元数据信息,包含{压缩前的大小,压缩后的大小,上一个Block的偏移信息,Checksum元数据信息}等信息
3.生成Checksum信息
4. Data Block以及Checksum信息通过HFile Writer中的输出流写入到HDFS中
5.为输出的Data Block生成一条索引记录,包含这个Data Block的{起始Key,偏移,大小}信息,这条索引记录被暂时记录到内存的Block Index Chunk中
至此,已经写入了第一个Data Block,并且在Block Index Chunk中记录了关于这个Data Block的一条索引记录。
随着Data Blocks数量的不断增多,Block Index Chunk中的记录数量也在不断变多。当Block Index Chunk达到一定大小以后(默认为128KB),Block Index Chunk也经与Data Block的类似处理流程后输出到HDFS中,形成第一个Leaf Index Block
bloom filter
scan
segment scanner
storefile scanner
scan match code