基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
HBaseAPI 过期数据删除功能
更新时间:2023-08-03 17:20:32
HBaseAPI 实现了过期数据删除(TTL)的能力,本文介绍如何通过命令或周期任务删除过期数据。
背景信息
OceanBase 数据库的 HbaseAPI 提供了过期数据删除的功能,用户可以为每一个 column family 指定数据的存活时间(Time To Live) 或者最大版本数 (MaxVersions),并通过命令或者设置周期性任务两种方式触发删除任务,从而减少存储空间占用。同时,对于 HBase 查询,OceanBase 数据库也会基于 TimeToLive 和 MaxVersions 对结果集进行过滤,避免给用户返回过期数据。
参数设置
通过在 comment 中添加 column family 的 HColumnDescriptor,设置 TimeToLive 和 MaxVersions 属性。HColumnDescriptor 必须是一个合法的 Json 对象字符串,格式如下:
注意
系统租户不提供 TTL 能力,即使给系统租户的表设置了 HColumnDescriptor,也不会执行 TTL 任务。
{
"HColumnDescriptor":
{
attribute: integer
...
}
}
| 参数 | 描述 |
|---|---|
| attribute | 填写参数 TimeToLive 或 MaxVersions。两个属性也可以同时设置,使用如下格式:{HColumnDescriptor": {"TimeToLive": 5, "MaxVersions": 2}}。 注意 同时设置 TimeToLive 和 MaxVersions 时,符合其中任意一个过期条件的记录都别视为过期。 |
| integer | 32 位的整型,且必须大于 0,否则作为无效值处理。
|
示例
创建 column family 时设置数据的存活时间为 5s,最大版本数量为 2:
CREATE TABLE htable1$family1 (
K varbinary(1024),
Q varbinary(256),
T bigint,
V varbinary(1048576) NOT NULL,
PRIMARY KEY(K, Q, T))
comment='{"HColumnDescriptor": {"TimeToLive": 5, "MaxVersions": 2}}'
PARTITION BY KEY(K) PARTITIONS 97;
column family 创建完成之后修改数据的存活时间为 6s,最大版本数量为 3:
ALTER TABLE htable1$family1 comment='{"HColumnDescriptor": {"TimeToLive": 6, "MaxVersions": 3}}'
使用说明
由于 OceanBase 数据库使用了 LSM Tree 架构(删除也是一个追加写的操作),即使通过 TTL 任务删除了过期数据,实际存储空间不仅有可能不降低,而且还可能增加,而最终存储空间的释放还是需要依靠 Major Compaction,因此建议配合 major freeze 同时使用,在 TTL 任务删除完成之后执行 major freeze,例如,可以通过设置 major_freeze_duty_time 在 kv_ttl_duty_duration 之后实现。
TTL 过期删除任务是一个后台低优先级任务,暂无法保证过期立即删除的能力,为了不对系统的性能造成较大影响,在任务的执行过程中如果遇到 memstore 内存 total_memstore_used 超过阈值 major_freeze_trigger(可以通过虚拟表 __all_virtual_tenant_memstore_info 或者视图 gv$memstore 查看)的情况,会暂停当前任务的执行直到内存降低到阈值以下。同时,为了不影响系统的恢复流程,对于正常进行物理恢复的租户,TTL 任务同样也会暂停该租户 TTL 任务的执行,直到租户完成恢复。
任务触发
触发 TTL 删除任务有两种方式,系统命令触发和定时任务触发。
系统命令触发
登陆到系统租户,并执行如下命令,触发所有租户的 TTL 任务:
ALTER SYSTEM trigger ttl;设置周期任务
登陆到您需要执行 TTL 任务的租户,执行如下命令设置租户每天 TTL 任务的触发时间:
alter system set kv_ttl_duty_duration = '[22:00:00, 24:00:00]'; // 默认值为 [00:00:00, 24:00:00] // 设置触发时间并打开 TTL 定时任务的开关:
ALTER SYSTEM SET enable_kv_ttl= true; // 默认值为 false
登陆到系统租户,并执行如下系统命令,可以挂起、恢复和取消正在执行的 TTL 任务。
ALTER SYSTEM suspend ttl; // 挂起当前正在执行的 TTL 任务
ALTER SYSTEM resume ttl; // 恢复当前挂起的 TTL 任务
ALTER SYSTEM cancel ttl; // 取消正在执行的 TTL 任务
查看任务状态
通过视图可以查看当前以及历史 TTL 任务的状态和相关信息,与 TTL 任务相关的视图有四张:
| 视图名称 | 视图作用 |
|---|---|
| DBA_OB_KV_TTL_TASKS | 查看当前租户正在执行的 TTL 任务 |
| DBA_OB_KV_TTL_TASK_HISTORY | 查看当前租户的历史 TTL 任务 |
| CDB_OB_KV_TTL_TASKS | 系统租户下查看所有租户正在执行的 TTL 任务 |
| CDB_OB_KV_TTL_TASK_HISTORY | 系统租户下查看所有租户的历史 TTL 任务 |
视图 DBA_OB_KV_TTL_TASKS 和 DBA_OB_KV_TTL_TASK_HISTORY 字段说明:
| 字段 | 说明 |
|---|---|
| TABLE_NAME | 表名 |
| TABLE_ID | 表 ID |
| PARTITION_ID | 分区 ID |
| TASK_ID | 任务 ID,从 1 开始 |
| START_TIME | 任务开始时间 |
| END_TIME | 任务结束时间 |
| TRIGGER_TYPE | 任务触发类型,包括 PERIODIC 和 USER 两种 |
| STATUS | 任务当前状态,见任务表状态说明 |
| TTL_DEL_CNT | 基于 TimeToLive 删除的记录数量 |
| MAX_VERSION_DEL_CNT | 基于 MaxVersions 删除的记录数量 |
| SCAN_CNT | 任务扫描的记录数量 |
| RET_CODE | 任务返回码 |
视图 CDB_OB_KV_TTL_TASKS 和 CDB_OB_KV_TTL_TASK_HISTORY 字段说明:
| 字段 | 说明 |
|---|---|
| TENANT_ID | 租户 ID |
| TABLE_NAME | 表名 |
| TABLE_ID | 表 ID |
| PARTITION_ID | 分区 ID |
| TASK_ID | 任务 ID,从 1 开始 |
| START_TIME | 任务开始时间 |
| END_TIME | 任务结束时间 |
| TRIGGER_TYPE | 任务触发类型,包括 PERIODIC 和 USER 两种 |
| STATUS | 任务当前状态,见任务表状态说明 |
| TTL_DEL_CNT | 基于 TimeToLive 删除的记录数量 |
| MAX_VERSION_DEL_CNT | 基于 MaxVersions 删除的记录数量 |
| SCAN_CNT | 任务扫描的记录数量 |
| RET_CODE | 任务返回码 |
说明
相比较 DBA 视图,只多了一个租户 ID。
任务状态说明
对于每一个租户的 TTL 任务,在实际执行时,会被拆分成设置了数据过期参数的 column family 表的分区任务,正在执行的租户任务和其分区任务都会被记录在任务表中,通过任务视图可以查看,历史分区任务会被移动到历史表中,通过历史视图可以查看。
注意
租户级任务的 TABLE_NAME 为 NULL,PARTITION_ID、TABLE_ID 均为 -1。
- 在任务视图 DBA_OB_KV_TTL_TASKS 和 CDB_OB_KV_TTL_TASKS 中,有两类任务:租户级任务和分区级任务,对应两类不同状态
- 在历史任务视图 DBA_OB_KV_TTL_TASK_HISTORY 和 CDB_OB_KV_TTL_TASK_HISTORY 中,只存在历史分区任务,所以只有分区任务状态。
分区任务状态:
| 任务状态 | 说明 |
|---|---|
| PREPARED | 准备状态,还未开始删除过期数据 |
| RUNNING | 运行状态,正在删除该分区过期数据 |
| PENDING | 挂起状态,可以通过命令恢复执行 |
| CANCELED | 取消状态,无法恢复执行 |
| FINISHED | 完成状态,待移动到历史表中 |
| INVALID | 非法状态 |
租户任务状态:
| 任务状态 | 说明 |
|---|---|
| RS_TRIGGERING | 表示正在给每个 observer 发送 TTL 过期任务 |
| RS_TRIGGERD | 表示所有 observer 已完成过期数据删除 |
| RS_SUSPENDING | 表示正在给每个 observer 发送 TTL 任务挂起请求 |
| RS_SUSPENDED | 表示所有 observer 已经完成 TTL 任务挂起 |
| RS_CANCELING | 表示正在给每个 observer 发送 TTL 任务取消请求 |
| RS_CANCELED | 表示所有 observer 已经完成 TTL 任务挂起 |
| RS_MOVING | 表示正在给每个 observer 发送 TTL 任务记录移动到历史表中的请求 |
| RS_MOVED | 表示所有 observer 已经完成 TTL 任务记录移动 |
| INVALID | 非法状态 |
设置历史任务清理周期
为了避免 TTL 历史任务堆积造成不必要的存储空间浪费,可以通过 kv_ttl_history_recycle_interval 配置项设置租户的历史 TTL 任务记录的保存时长(默认为 7 天):
ALTER SYSTEM SET kv_ttl_history_recycle_interval= '30d'; // 设置自动清理超过 30 天的历史 TTL 任务记录
示例:定时删除过期数据
创建一个 column family 表:
CREATE TABLE t1$cf1 ( K varbinary(1024), Q varbinary(256), T bigint, V varbinary(1048576) NOT NULL, PRIMARY KEY(K, Q, T)) comment='{"HColumnDescriptor": {"TimeToLive": 1800, "MaxVersions": 2}}' PARTITION BY RANGE columns(K) ( partition p1 values less than ('row2'), partition p2 values less than ('row3'), partition p3 values less than ('row4'), partition pm values less than (MAXVALUE) );模拟 HbaseAPI 插入数据,实际插入数据过程请参考 HBaseAPI 客户端使用介绍。
INSERT INTO t1$cf1 VALUES ("row1", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"), ("row1", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"), ("row2", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"), ("row2", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"), ("row3", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"), ("row3", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del"), ("row4", "cq1", -truncate(time_to_usec(date_sub(now(), interval +1 hour))/1000, 0), "del"), ("row4", "cq1", -truncate(time_to_usec(now())/1000, 0), "no del");设置租户每日 TTL 任务时间并打开定时任务开关。
ALTER SYSTEM SET kv_ttl_duty_duration = '[00:00:00, 23:59:59]'; // 从 0 点开始,会尝试执行一次 TTL 任务,如果 23:59:59 前任务尚未完成,会自动挂起,待明天继续执行 ALTER SYSTEM SET enable_kv_ttl= true; // 开启定时任务查看任务执行状态。
查看当前任务(执行结果取决于实际任务执行状态)
OceanBase(root@test)>select * from oceanbase.dba_ob_kv_ttl_tasks; +------------+----------+--------------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ | TABLE_NAME | TABLE_ID | PARTITION_ID | TASK_ID | START_TIME | END_TIME | TRIGGER_TYPE | STATUS | TTL_DEL_CNT | MAX_VERSION_DEL_CNT | SCAN_CNT | RET_CODE | +------------+----------+--------------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ | NULL | -1 | -1 | 1 | 2022-07-05 10:22:44.656768 | 2022-07-05 10:22:44.656768 | PERIODIC | RS_TRIGGERING | 0 | 0 | 0 | OB_SUCCESS | +------------+----------+--------------+---------+----------------------------+----------------------------+--------------+---------------+-------------+---------------------+----------+------------+ 1 row in set查看历史任务(执行结果取决实际任务执行状态)
OceanBase(root@test)>select * from oceanbase.dba_ob_kv_ttl_task_history; +------------+------------------+--------------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ | TABLE_NAME | TABLE_ID | PARTITION_ID | TASK_ID | START_TIME | END_TIME | TRIGGER_TYPE | STATUS | TTL_DEL_CNT | MAX_VERSION_DEL_CNT | SCAN_CNT | RET_CODE | +------------+------------------+--------------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ | t1$cf1 | 1100611139453777 | 0 | 1 | 2022-07-05 10:22:48.204789 | 2022-07-05 10:22:48.205930 | PERIODIC | FINISHED | 1 | 0 | 2 | OB_SUCCESS | | t1$cf1 | 1100611139453777 | 1 | 1 | 2022-07-05 10:22:48.199108 | 2022-07-05 10:22:48.200199 | PERIODIC | FINISHED | 1 | 0 | 2 | OB_SUCCESS | | t1$cf1 | 1100611139453777 | 2 | 1 | 2022-07-05 10:22:48.193446 | 2022-07-05 10:22:48.194713 | PERIODIC | FINISHED | 1 | 0 | 2 | OB_SUCCESS | | t1$cf1 | 1100611139453777 | 3 | 1 | 2022-07-05 10:22:48.210228 | 2022-07-05 10:22:48.211169 | PERIODIC | FINISHED | 1 | 0 | 2 | OB_SUCCESS | +------------+------------------+--------------+---------+----------------------------+----------------------------+--------------+----------+-------------+---------------------+----------+------------+ 4 rows in set
查看当前 column family 表中的数据。
OceanBase(root@test)>select * from t1$cf1; +------+-----+----------------+--------+ | K | Q | T | V | +------+-----+----------------+--------+ | row1 | cq1 | -1656987738000 | no del | | row2 | cq1 | -1656987738000 | no del | | row3 | cq1 | -1656987738000 | no del | | row4 | cq1 | -1656987738000 | no del | +------+-----+----------------+--------+ 4 rows in set