HBase进阶

HBase进阶

总是找不到合适的开场白,哎。。。

RegionServer架构

在这里插入图片描述

StoreFile

  • 保存实际数据的物理文件,StoreFile以HFile的形式存储在HDFS上。
  • 每个Store会有一个或多个StoreFile(HFile),数据在每个StoreFile中都是有序的。

MemStore

  • 写缓存。
  • 由于HFile中的数据要求是有序的,所以数据是先存储在MemStore中,排好序后,等到达刷写时机才会刷写到HFile,每次刷写都会形成一个新的HFile

WAL

  • 由于数据要经MemStore排序后才能刷写到HFile,但把数据保存在内存中会有很高的概率导致数据丢失。
  • 为了解决这个问题,对数据的操作行为会先写在一个叫做Write-Ahead logfile的文件中,然后数据再写入MemStore中。
  • 所以在系统出现故障的时候,数据可以通过这个日志文件重建。

BlockCache

  • 读缓存
  • 每次查询出的数据会缓存在BlockCache中,方便下次查询。

写流程

在这里插入图片描述

写流程:

  • Client先访问ZooKeeper,获取hbase:meta表位于哪个RegionServer
  • Client访问对应的RegionServer,获取hbase:meta表。根据写请求的namespace:table/rowkey,查询出目标数据位于哪个RegionServer的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在Client的meta cache,方便下次访问。
  • 与目标Region Server进行通讯
  • 将数据顺序写入(追加)到WAL
  • 将数据写入对应的MemStore,数据会在MemStore进行排序
  • 向客户端发送ack
  • 等达到MemStore的刷写时机后,将数据刷写到HFile

MemStore Flush

在这里插入图片描述

MemStore刷写时机:

  • 某个memStore的大小
当某个memStore的大小达到了
hbase.hregion.memstore.flush.size(默认值128M),
其所在的region的所有memStore都会刷写。
当memStore的大小达到了
hbase.hregion.memstore.flush.size(默认值128M) * hbase.hregion.memstore.block.multiplier(默认值4)时,
会阻止继续往该memStore写数据。
  • regionServer中memStore的总大小
当regionServer中memStore的总大小达到
java_heapsize * hbase.regionserver.global.memstore.size(默认值0.4) * hbase.regionserver.global.memstore.size.lower.limit(默认值0.95),
region会按照其所有memStore的大小顺序(由大到小)依次进行刷写。直到regionServer中所有memStore的总大小减小到上述值以下。
当regionServer中memStore的总大小达到
java_heapsize * hbase.regionserver.global.memstore.size(默认值0.4)时,
会阻止继续往所有的memStore写数据。
  • 到达自动刷写时间
自动刷新的时间间隔由该属性进行配置:
hbase.regionserver.optionalcacheflushinterval(默认1小时)
  • WAL文件的数量
当WAL文件的数量超过hbase.regionserver.max.logs,
region会按照时间顺序依次进行刷写,直到WAL文件数量减小到hbase.regionserver.max.log以下
(该属性名已经废弃,现无需手动设置,最大值为32)。

以Region为单位进行Flush。尽可能减少列族的数量,最好一个,最多不要超过三个。

读流程

在这里插入图片描述

读流程:

  • Client先访问Zookeeper,获取hbase:meta表位于哪个RegionServer。
  • Client访问对应的RegionServer,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个RegionServer中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache,方便下次访问。
  • 与目标RegionServer进行通讯。
  • 分别在MemStore和StoreFile(HFile)中查询目标数据,若BlockCache中已存在就直接获取而不用读取StoreFile,并将查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(timeStamp)或者不同的类型(Put/Delete)。
  • 将查询到的新的数据块(Block,HFile数据存储单元,默认大小为64KB)缓存到Block Cache。
  • 将合并后的最终结果返回给客户端。

小结

  • 源码中有几个重要的对象:regionScanner,storeScanner,memStoreScanner,HFileScanner
  • scanner不会立刻去扫描数据。而是会先对scanner做一层过滤,按照时间范围,rowkey范围,布隆过滤器进行过滤,留下的scanner才会去读取数据。
  • 读文件首先会去读索引,再根据索引定位到Block。会先去Block Cache中查找有没有对应的Block,如果有就返回;若没有就读取文件,再将新block更新到Block Cache中。
  • 索引位于HFile中,每个HFile都有自己的索引,只有当RegionServer第一次访问HFile时,才会去加载索引存放到Block Cache中。每个文件的布隆过滤器也存放在Block Cache中。
  • 索引:根据rowkey的范围对应一个block
  • block cache 存放:数据,索引文件,布隆过滤器

布隆过滤器:存在于每个HFile中,当flush时生成第一次访问HFile,会将布隆过滤器放在Block Cache中。

  • 可以把布隆过滤器当成一个数组,数组中存放的要么是0,要么是1
  • 怎么生成:刚开始全是0。有若干个hash函数,每条数据都有自己的rowkey,经过每一个hash函数,返回的结果会指向数组中的某个位置,然后置成1。
  • 怎么用:读数据时先加载布隆过滤器,判断有没有想要的rowkey,经过若干个hash函数,若数组中都是1,则有可能存在。能够百分百的否定rowkey,排除部分HFile。

StoreFile Compaction

由于memStore每次flush都会生成一个新的HFile,且同一个字段的不同版本(timeStamp)和不同类型(Put/Delete)有可能会分布在不同的HFile中,因此查询时需要遍历所有的HFile。为了减少HFile的个数,以及清理掉过期和删除的数据,会进行storeFile Compaction。

Compaction会分为两种,分别是Minor CompactionMajor Compaction。Minor Compaction会将临近的若干个较小的HFile合并成一个较大的HFile,并清理掉部分过期和删除的数据。Major Compaction会将一个Store下的所有的HFile合并成一个大HFile,并且会清理掉所有过期和删除的数据

在这里插入图片描述

Region Split

默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的Region Server,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的Region Server。

在这里插入图片描述

Region Split时机:

  • ConstantSizeRegionSplitPolicy(0.94版本之前默认切分策略)

当一个region中的某个store下所有的storeFile的总大小超过hbase.hregion.max.filesize(默认10G),该Region就会进行拆分。

  • IncreasingToUpperBoundRegionSplitPolicy(0.94版本~2.0版本默认切分策略)

当一个region中的某个store下所有的storeFile的总大小超过Min(initialSize*R^3 ,hbase.hregion.max.filesize"),该Region就会进行拆分。
其中initialSize的默认值为2*hbase.hregion.memstore.flush.size,R为当前RegionServer中属于该Table的Region个数

具体的切分策略为:
第一次split:1^3 * 256 = 256MB
第二次split:2^3 * 256 = 2048MB
第三次split:3^3 * 256 = 6912MB
第四次split:4^3 * 256 = 16384MB > 10GB,因此取较小的值10GB
后面每次split的size都是10GB
  • SteppingSplitPolicy(2.0版本默认切分策略)

如果当前RegionServer上该表只有一个Region,按照2 * hbase.hregion.memstore.flush.size分裂,否则按照hbase.hregion.max.filesize分裂。

其他的切分策略:

  • DisableRegionSplitPolicy(meta表默认切分策略)

禁止Region split

  • KeyPrefixRegionSplitPolicy

切分策略依然依据默认切分策略。 根据RowKey指定长度的前缀来切分Region,保证相同的前缀的行保存在同一个Region中。
由KeyPrefixRegionSplitPolicy.prefix_length属性指定RowKey前缀长度。按此长度对splitPoint进行截取
此策略比较适合有固定前缀的RowKey。当没有设置前缀长度,切分效果等同与IncreasingToUpperBoundRegionSplitPolicy。

  • DelimitedKeyPrefixRegionSplitPolicy

切分策略依然依据默认切分策略。 同样是保证相同RowKey前缀的数据在一个Region中,但是是以指定分隔符前面的前缀来切分Region。

Split流程小结

  • 预分区也会split。
  • 在Region中找到一个合适的split point,在这个split point上将该Region的数据划分为两个新的Region。
  • Split发生时,新创建的子Region不会立即将所有数据重新写入新文件,而是会创建引用文件,指向老Region中的数据。
  • meta表中保存新Region,删除老Region。
  • 读数据时会去老Region中读,但是写数据会写在新Region中
  • 在major compaction时,会将老Region的数据移动到新Region,删除老Region。
  • Master默认5分钟自动负载均衡。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值