HBase_04_架构原理详解

4 HBase进阶

4.1 RegionServer架构

image-20201212155829185

image-20201214091250740

①HMaster

HMaster:HBase中用来管理集群中的HRegionServer的一个进程。

当集群中Regionserver所在的节点宕机了,HMaster会重新在集群中启动一个RegionServer。

RegionServer宕机了并不会导致数据丢失,因为数据都保存在HDFS上,重新启动的RegionServer重新去HDFS上读数据就可以了。

②HRegionServer

HRegionServer:HBase中用来管理内部存放的HRegion的一个进程。

③HRegion

HRegion:类似于水平拆分的表(表的一段数据),类似于Kafka中的分区的概念,一张表被分成多个region,多个region可能放在不同的节点上。

④Block Cache

BlockCache:块缓存(读缓存),用来提高查询效率

当查询一条数据,会先从BlockCache中查,查不到再去写缓存(memStore)中找,再查不到就去StoreFile中找。找到的数据会放在BlockCache中。

⑤WAL

WAL:write ahead log,预写日志。用来恢复数据。

由于数据要经MemStore排序后才能刷写到HFile,但把数据保存在内存会有较高的概率导致数据丢失,为了解决这个问题,数据会先写在一个Write-Ahead-Logfile的文件中,然后再写入MemStore中。

  • 系统出现故障,会根据这个WAL日志文件重建。
  • 注意!WAL有多个,WAL是以Region为单位的。

HBase故障恢复:

Zookeeper依靠心跳检测发现节点故障,然后HMaster会收到Region Server故障的通知,将WAL给其他Region Server进行回放,建立MemStore。

在写数据的时候,会将数据写到memStore中,写入内存会更快。但是写入内存中就有可能丢失数据,所以在写入memStore之前,先写入到WAL中。防止RegionServer故障,数据丢失。

⑥HStore

HStore:存储,面向列存储;一个列族就有一个Store,所以Region中可能有多个Store

⑦HStoreFile

HStoreFile:Store所存储的文件

如果Memstore中数据太多,那么会影响内存的使用,所以当达到阈值的时候,hbase会对Memstore进行刷写(flush)操作,将内存的数据写入磁盘,这个磁盘文件就是StoreFile。

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

⑧MemStore

MemStore:内存存储,主要用于存储新增(修改、删除)的数据,类似于缓冲区(buffer)

写数据的时候,先不着急写入到StoreFile中,先写如MemStore中。

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

  • 保存在内存中,会有很大概率丢失数据。==> WAL

⑨Meta Table

MetaTable是一个特殊的HbaseTable,它保存了系统中所有的region列表。这张table类似于一个b-tree。结构大致如下:

  • Key:table,region start key,region id
  • Value:region server

4.2 读流程

image-20201219102709519

读操作,要比写麻烦,是因为读会先从BlockCache中读数据,没有再去MemStore读数据,没有再去StoreFile读数据。

为什么要去MemStore读数据?这是因为刚写的数据,有很大的概率会读。

读出来的数据,就要放到BlockCache,读缓存中。因为刚读出来的数据,有很大的概率会再次读取。

读数据流程:

  1. Client先访问zookeeper,获取hbase:meta表位于哪个RegionServer

  2. 访问对应的RegionServer,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个RegionServer中的哪个Region中。并将该Table的region信息以及meta表的位置信息缓存在客户端的meta cache,方便下次访问。

  3. 找到对应的RegionServer。

  4. 分别在BlockCache和MemStore和StoreFile中查询目标数据,并将查到的所有数据进行合并,此处的所有的数据是指同一条数据的不同版本(time stamp)或者不同的类型(put/delete)

    • 读流程相比写流程效率低,就是因为写是直接写到WAL然后写到memstore就可以了,但是查询要先到BlockCache中查,然后到Memstore中查,然后到StoreFile中查询。因为查询的结果可能存在这三个位置,所以还需要将这三个地方的查询结果合并。

    • 但是HFile可能很多,所以为了避免查询的效率低,需要对HFile文件进行过滤,先采用布隆过滤器进行过滤。

  5. 将查询到的新的数据块(Block,Hfile数据的存储单元,默认大小64KB)缓存到BlockCache中

  6. 将合并后的结果返回给客户端。

布隆过滤器

查询的时候,可能会从很多的HFile中去查询,那么这么多HFile肯定会影响查询性能,那么怎么去过滤掉一些HFile呢?

布隆过滤器:就可以判断出数据不在HFile中。

原理:通过对要查询的数据,hash定位找到在HFile中的索引位置,那么去判断这个位置是否有值。

可以过滤掉一些 一定不存在的文件。

image-20210114201252781

4.3 写流程

为了能够确定增加数据时,数据在哪一个节点的region中,所以客户端首先要查询hbase:mata表信息,但是由于meta也是一张表,所以这张表在哪里不能确定。所以必须先访问zookeeper,获取meta表在哪个节点上

image-20201215083557006

写数据流程:

  1. Client先访问Zookeeper,获取hbase:meta表位于哪个RegionServer

    meta表不管多大,只能放在一个Region上,只能放在一个RegionServer上

    image-20201218082146887

  2. 访问对应的RegionServer,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个RegionServer中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache中,方便下次访问。

    image-20201218084914429

  3. 与目标的RegionServer进行通信。

  4. 将数据顺序写入(追加)到WAL,读缓存中。

  5. 将数据写入对应的MemStore中,数据在MemStore中进行排序。

  6. 向客户端发送ack。

  7. 等达到MemStore的刷写时机后,将数据刷写到HStoreFile中。

    image-20201218083337888

写数据的时候,比如有一个rowkey=1001,怎么知道放到哪一个region中呢?

会通过HMaster找到Zookeeper上的hbase信息,得到meta在哪台RegionServer上;然后访问该RegionServer上的meta表,可以查到要写入的数据位于RegionServer中的哪个Region中。

4.4 MemStore flush

默认是两个线程处理flush

补充:WAL也是会触发刷写的

WAL一直往里面写,也会太大,WAL太大,那么MemStore也有可能太大,那么会触发flush,memstore的数据落盘之后,WAL中的数据就可以删掉了。落盘了数据安全了,WAL内的数据就没有必要了。

①Flush时机

(1)当某个memstore的大小达到了hbase.hregion.memstore.flush.size(默认值128M),其所在的region的所有memstore都会刷写。

​ 当memstore的大小达到了128M*4时,会阻止继续往该memstore写数据。

hbase.hregion.memstore.flush.size(128M)
hbase.hregion.memstore.block.multiplier(4)

(2)当region server中memstore的总大小达到 java_heapsize * 0.4 * 0.95。region会按照其所有memstore的大小顺序(由大到小)依次进行刷写。直到region server中所有memstore的总大小减小到上述值以下。

​ 当region server中memstore的总大小达到java_heapsize * 0.4时,会阻止继续往所有的memstore写数据。

java_heapsize
hbase.regionserver.global.memstore.size(0.4)
hbase.regionserver.global.memstore.size.lower.limit(0.95)

(3)当达到自动刷写时间(默认1小时),也会触发memstore flush。自动刷写的时间间隔由该属性进行配置:

hbase.regionserver.optionalcacheflushinterval(默认1小时)
-- 3600000

(4)当WAL文件的数量超过hbase.regionserver.max.logs,region会按照时间顺序依次进行刷写,直到WAL文件数量减小到hbase.regionserver.max.logs以下。(该属性名已经废弃,现无需手动设置,最大值为32)。

②如何验证flush

在HDFS上的/hbase/data/test/person/f43774001f551b4f3cdd264cda0dc640/info路径下,对于刚创建的person表,是没有东西的。

我们往person表中添加数据:

hbase(main):006:0> put 'test:person','1001', 'info:name', 'Tom'
hbase(main):009:0> put 'test:person', '1002', 'info:name', 'Jerry'

这个时候并没有到达刷写时机,所以不会出现文件。我们手动刷写:

hbase(main):008:0> flush 'test:person'

这个时候可以在HDFS的路径中看到:

image-20201219101825681

4.5 StoreFile的Compaction

①为什么合并?

  • 合并compact的原因:

    • 由于memstore每次刷写都会生成一个新的HFile,并且同一个rowkey字段的不同版本(timestamp)和不同类型(put/delete)有可能会分布在不同的HFile中,因此查询时需要遍历所有的HFile。

      还会有一些标记删除的数据,也需要在合并的时候删除掉。

      image-20210114221017198

    • 上面这样的flush会产生很多小文件

  • 目的:为了在合并的时候①清理掉过期和删除的数据,②减少小文件HFile的个数,会进行StoreFile Compaction

②Compaction分类

Minor Compaction:会将临近的若干个小文件HFile合并成一个较大的HFile。

Major Compaction:会将一个Store下的所有HFile合并成一个大的HFile,并且会清理掉所有过期和删除的数据。(所以上图的minor compaction不能清理和删除数据了~)

image-20210114221731557

③验证compact合并

手动触发合并机制:major_compact ‘表’

hbase(main):016:0> major_compact 'test:person'

得过一段时间,刷新HDFS,可以看到小文件合并了

image-20201219102409824

4.6 Region Split

  • 默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region出现**热点分区(某个region数据太多)**会自动进行拆分。

  • 拆分时,两个子Region都位于当前的RegionServer,但是考虑到负载均衡,HMaster有可能会将某个Region转移给其他的RegionServer。

    但是!切分的时候并不会把一个rowkey的数据分到不同的Region中!

    image-20210114222505718

①Region Spilt时机

(1)当1个Region中的某个Store下所有的StoreFile的总大小超过hbase.hregion.max.filesize,该Region就会拆分。(HBase0.9版本之前)

(2)当1个Region中的某个Store下所有的StoreFile的总大小超过Min(initialSize *R^3 ,hbase.hregion.max.filesize"),该Region就会进行拆分。其中initialSize的默认值为2 *hbase.hregion.memstore.flush.size,R为当前Region Server中属于该Table的Region个数(0.94版本之后)。

具体的切分策略为:
第一次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了。

(3)Hbase 2.0引入了新的split策略:如果当前RegionServer上该表只有一个Region,按照2 * hbase.hregion.memstore.flush.size分裂,否则按照hbase.hregion.max.filesize分裂。

"现在版本中具体的切分策略"--① 如果当前RegionServer上该表只有一个Region:Region达到256M就Split
2 * hbase.hregion.memstore.flush.size = 2 * 128 = 256M
--② 如果当前RegionServer上该表有多个Region:Region达到10GB就Split
hbase.hregion.max.filesize = 10GB

猜你喜欢

转载自blog.csdn.net/qq_43523503/article/details/113531458
今日推荐