清理MOB文件的线程
MOB表中的mob文件有时候也需要清理,当MOB文件满足如下条件时,需要对其进行清理。
- MOB文件中的数据已经过期无用,此时该MOB文件就可以被清理删除
- 若干个小的MOB文件被合并之后,老的MOB文件不再被任何region所引用,此时也可以被清理删除
针对MOB文件的清理,HBase提供了两个线程任务来执行,分别是RSMobFileCleanerChore
和MobFileCleanerChore
,两者的特点如下。
MobFileCleanerChore
- 调用者:HMaster服务调用执行
- 范围:针对整个HBase集群的MOB文件进行清理
- 清理对象: 创建时间超过TTL时间的MOB文件
RSMobFileCleanerChore
- 调用者: RegionServer
- 范围: 仅清理位于当前RegionServer上的Region所引用的MOB文件
- 清理对象:没有被任何region引用的MOB文件,属于被清理的对象
下面针对这两个MOB清理任务,分别进行详细说明。
MobFileCleanerChore
工作机制
前提条件
只有满足如要条件的列族,MobFileCleanerChore
才会对其执行清理操作
- 列族是MOB类型
- 列族配置的最小保存版本数为0,如果不为0,则不执行
- 列族配置了TTL
如下所示。
1 | // 检查列族是否是MOB类型, 最小保存的版本数是否为0 |
MobFileCleanerChore
的判定条件
获取过期时间
MobFileCleanerChore
任务是周期性任务,默认情况下,一天执行一次。
在执行时,会首先获取当前时间current
,然后根据列族的TTL时间,计算一个过期时间,然后MOB文件时间在这个过期时间之前的,都认为是已经过期的文件,是可以被删除的。
如现在时间是2024-09-26 12:00:00
, TTL是1天,则计算的过期时间是2024-09-26 12:00:00
,然后再对时分秒清零,因此过期时间是2024-09-26 00:00:00+000
1 | Calendar calendar = Calendar.getInstance(); |
这里需要说明下为什么要对时分秒清零?
因为MOB文件名中包含时间字符串,但是该字符串是不包含时分秒等数据。
获取MOB文件的时间
MOB文件名的格式如下所示。
1 | d41d8cd98f00b204e9800998ecf8427e20240925221150b7685c4bf5bcba54c97658e3dd_63f50cb1b677b063afc5bcd56c703e2e |
其中文件名字符串的32-39位表示的是该文件的创建时间,HBase通过解析该文件名字符串获取到MOB文件的创建时间。
MOB文件的时间来源
MOB数据,在写入的时候也是会首先写入到Memstore,只是在flush的时候,会将元数据信息存放在hfile中,真实的数据会存储在MOB文件中。
HBase在flush的时候,会根据暂存在memstore中的KV数据的时间戳来确定MOB文件的时间,如果存在多个KV,则以最新的时间戳最为生成MOB文件的时间。
示例:
1 | 1727061887ms = 1970-01-01 08:00:02 |
如上所示,我们往mob表中写入了3个KV,其中最新的时间戳是第二个,时间是1727061887000
, 因此生成的MOB文件时间就是*20240923*
。
对比时间
由于MOB文件时间是当前文件中最新KV的时间戳,因此只要该时间过期,那么意味着该文件中的所有数据都是过期的,因此都可以删除。
通过过期时间和MOB文件时间的对比,如果MOB文件时间处于过期时间之前的,则认为过期。
比较时间的时候,忽略时分秒是否会删除未过期的数据?
答案是不会。原因:
对于MOB过期文件,hbase是允许多存一些时间的。
比较过期时间时,忽略了时分秒,意味着是以天为单位来进行比较的;且比较时是将早于过期时间的MOB文件判定为过期fileDate < 过期时间
,这意味着即使当天过期的MOB文件,也会继续保留一段时间,在第二天才会被删除,因此不会删除未过期的时间。举例说明:
ttl=1s,MOB文件时间是2024-10-20
,假设已经过期,MobFileCleanerChore
在2024-10-20 12:00:00
开始运行,计算出的过期时间是2024-10-20 00:00:00
,由于fileDate < 过期时间
这个条件不成立,因此本次运行不会将其认定为过期。 只有在2024-10-21 00:00:01
时刻及之后,该任务运行,才会判定该MOB文件过期。
RSMobFileCleanerChore
工作机制
前提条件
只有满足如下如要条件的列族,RSMobFileCleanerChore
才会对其执行清理操作
- 列族是MOB类型
代码如下所示。
1 | List<ColumnFamilyDescriptor> list = MobUtils.getMobColumnFamilies(htd); |
RSMobFileCleanerChore
的执行流程
- 获取当前RegionServer上的表,针对每个表,有如下操作
- 遍历每个表的Region
- 针对每个Region,遍历其所有列族
- 找到该region下的MOB列族,遍历列族下的所有hfile文件,并进行如下操作
- 读取hfile,获取元数据信息
- 元数据信息获取该hfile文件是否引用有MOB文件(原因是MOB列族中也可能写入小数据,此时是不生成MOB文件的)
- 如果hfile文件引用有MOB文件,则记录该MOB文件信息;没有继续进行下一个hfile文件的判断
- 找到该region下的MOB列族,遍历列族下的所有hfile文件,并进行如下操作
- 针对一个表,记录完毕所有满足条件的MOB文件信息
- 再次针对这个表的MOB列族,进行如下操作
- 遍历每个MOB列族
- 针对每个MOB列族,获取对应的mobdir目录下的所有mob文件,针对文件,进行如下操作
- 根据文件名信息获取引用该MOB文件的region name
- 基于region name判断该region是否在当前的这个RegionServer上,如果不在,跳过该MOB文件;如果在,进行下一步操作
- 判断该MOB文件是否被region引用(和上面的记录信息比较),如果存在,则跳过该MOB文件;如果不存在,则说明没有引用,可以进行下一步操作
- 判断该MOB文件的最后更新时间是否超过阈值(默认是1h),如果超过,则将其归档清理;不超过,则不归档
总结
虽然HBase中存在两类清理MOB文件的线程,RSMobFileCleanerChore
和MobFileCleanerChore
。
但是两者的作用是完全不同的。
MobFileCleanerChore
线程,主要用于清理TTL过期的MOB文件,针对的是设置有TTL配置的MOB列族RSMobFileCleanerChore
线程,主要用于清理无用的MOB文件,针对的是MOB表中的所有MOB列族。