RegionServer是Hbase系统中最核心的组件,主要负责用户数据写入、读取等基础操作。

一、RegionServer内部结构

cdh调整hbase的内存 控制hbase内存写入的组件_hbase

一个RegionServer由一个或多个HLog、一个BlockCache以及多个Region组成。

Hlog保证数据写入的可靠性,BlockCache缓存提升数据读取性能,Region时表的数据分片,通常一个RegionServer负责多个Region的数据读写。

一个Region由多个Store组成,每个Store放对应列簇的数据。

每个Store包含一个MemStore和多个Hfile。数据在写入时首先写入到MemStore,达到一定大小会落盘形成Hfile

二、Hlog

Hbase中系统故障恢复以及主从复制都基于HLog实现。

默认情况下,所有增删改的数据都先以追加形式写入HLog,再写MemStore,最后落盘形成HFile。如果RegionServer发生异常宕机,未落盘的数据通过回放HLog补救数据。

HLog文件结构:

     

cdh调整hbase的内存 控制hbase内存写入的组件_数据库_02

        1、每个RegionServer拥有一个或多个HLog(默认是1,1.1版本可以开启MultiWAL,允许多个HFLog)。每个HLog是多个Region共享的。

         2、HLog中每一个小方框为一个日志单元 WALEntry,表示一次行级更新的最小追加单元。由HLogKey和WALEdit组成,其中

        HLogKey由tablename,region name,sequenceid等字段构成。

        WALEdit用来表示一个事务中的更新集合。Hbase将一个行级书屋的写入操作表示为一条记录。

HLog文件存储:

        Hbase中所有的数据,包括HLog以及实际数据,都存储在HDFS的指定路径(配置文件设置的)。之前介绍过Hbase在HDFS上数据存储的目录分别有什么意义。HLog存储在两个位置:

WALs存储的是未过期的日志,oldWALs存储过期未清楚的日志。通常情况写WALs下会有多个子目录,每个子目录代表一个对应的RegionServer

Hlog生命周期:

HLog生命周期包括4个阶段:

1、HLog创建:Hbase的任何更新删除的操作都会将记录追加到HLog文件中。

2、HLog滚动:Hbase后台启动一个线程,每个一段时间(hbase.regionserver.logroll.period指定,默认1小时)进行日志滚动。会创建一个新的日志文件。日志以滚动文件的形式存在,方便删除过期数据。

3、HLog失效:写入数据一旦从MemStore中落盘,对应的日志数据就会失效。失效的日志文件会从WALs路径移动到oldWALs下。这里还没有彻底删除。

4、HLog删除:Master后台会启动一个线程,每个一段时间(hbase.master.cleaner.interval,,默认1分钟)检查一次文件夹oldWals下的所有失效日志文件,确认是否可以删除,确认条件主要有两个:

        1、HLog文件是否还在参与主从复制。

        2、该HLog是否已经在oldWALs路径下存在10分钟(hbase.master.logcleaner.ttl,默认10分钟),最多保留10分钟。

三、MemStore

        Hbase系统中就爱你给他一个表水平切分成多个Region,每个Region负责自己区域的数据读写请求,水平切分意味着每个分片中都包含了所有的列簇数据。Hbase将不同列簇的数据存储在不同的Store中,每个Store由一个MemStore和一个或多个HFile组成。

cdh调整hbase的内存 控制hbase内存写入的组件_cdh调整hbase的内存_03

 Hbase基于LSM数模型实现,数据首先写入HLog,再写入MemStore,达到一定大小超过阈值之后数据落盘形成HFile。LSM具有以下几个非常明显的优势:

        1、将一次随机IO写入转换成一个顺序IO写入(HLog写入)加上一次内存写入(MemStore 写入),提升写入性能。

        2、HFile中KeyValue数据需要按照Key排序,排序之后可以在文件级别根据有序的key创建索引树,提升读取效率。

        3、MemStore作为一个缓存集的存储组件,缓存着最近写入的数据。最新写入的数据被读取的概率会更大,提升读取性能

        4、在写入HFile之前,可以在内存中对KeyValue进行更多的优化。在写出之前会将数据合并,处理掉过期的数据,保留最近几个版本(文件版本通过建表设置)

MemStore内部结构:

        在实际实现中,Hbase采用了跳跃表的数据结构,Hbase没有使用原始的跳跃表,而是使用JDK自带的ConcurrentSkipListMap,底层使用跳跃表来保证数据的有序性,查找写入删除操作可以在O(logN)时间内完成。还实现了CAS原子操作(线程锁),保证数据的数据的原子性。

        MemStore有两个跳跃表,当数据写满一个跳跃表时,此跳跃表A不再接受数据,由跳跃表B接受数据。跳跃表A执行flush落盘。

MemStore的GC问题:

        MemStore本质上就是一个缓存。在工作中,数据更新删除会导致内存中出现大量的内存碎片,当没有一个内存碎片可以存储数据时,就会出发FULL GC。

        因为一个RegionServer由多个Region组成,一个Region有由多个MemStore组成,所有的MemStore内存共享。当有的MemStore数据落盘,内存就会空出来,形成内存碎片。

cdh调整hbase的内存 控制hbase内存写入的组件_cdh调整hbase的内存_04

 从JVM全局的视角来看,随着MemStore中数据不断写入并且flush,整个JVM会产生越来越小的内存条带,随着堆积增多,导致已经不能分配出足够大的内存给写入的数据,就会出发FULL GC。

MSLAB内存管理方式: