feat(config): add config history cleanup feature with retention days setting
🔧 Feature: Config History Cleanup with Retention Setting 💡 Background The his_config_info table records every configuration change, and it can grow rapidly in production environments (millions of rows). Without a proper cleanup mechanism, this may cause:
Poor query performance Increased storage costs and backup overhead Operational risk during upgrades or restores This PR introduces a configurable cleanup mechanism to automatically remove outdated configuration history.
✨ What’s New New config options: properties
history.cleanup.enabled=true # Enable/disable history cleanup history.retention.days=180 # Retain config history for N days history.cleanup.time=03:00 # Daily cleanup time (optional) A scheduled task runs once per day to remove entries from his_config_info older than the configured number of days. All cleanup operations are logged with affected row counts. ✅ Compatibility Backward compatible: Cleanup is disabled by default. No schema changes introduced. 📦 Example properties
Retain config change history for the last 6 months
history.cleanup.enabled=true history.retention.days=180
背景
his_config_info 表随着时间增长可能出现百万甚至千万级数据,影响性能和备份。本 PR 提供一个通用的清理机制,让用户可以通过配置指定历史记录的保留天数。
变更内容
- 新增配置项:
history.cleanup.enabledhistory.retention.dayshistory.cleanup.time(可选)
- 每天定时任务执行清理
- 清理日志记录影响行数
兼容性
向下兼容: 清理功能默认关闭。 不涉及任何数据库结构变更。
示例配置
history.cleanup.enabled=true history.retention.days=180
@i will solve it@
我记得好像之前有issue , 忘记是否已经解决过了。
@wqyenjoy 提pr前,建议先把方案提交到issue里,讨论一下,避免实现之后发现方案有问题。
OK,我先构思下方案。
原本的实现是这样的:
触发机制简单:服务启动后延迟 10 分钟执行,每 10 分钟重复调度一次; 节点选择:仅由集群中 IP 最小的节点执行,作为“简易主节点”; 清理方式:每次按保留天数(默认 30 天)删除过期记录,分批每 1000 条; 调度不可控:无法指定具体清理时间点、无法关闭,执行日志较粗略; 实现基础:基于 TimerTaskService.scheduleWithFixedDelay() + isFirstIp() 判定。
新的实现想尽量兼容老设计
原设计行为 | 新实现如何处理
使用 nacos.config.retention.days | 保留原参数,继续作为保留天数的主要控制项 无法关闭清理逻辑 | 增加 history.cleanup.enabled 控制是否启用 固定 10 分钟调度 | 改为 Cron 可配时间点,默认每天凌晨 3 点,避免业务冲突 isFirstIp() 判定主节点 | 改为基于 Raft 的 hasLeadership() 判断,更稳定 无清理日志或观测能力 | 增强日志输出,记录删除总数和过期时间范围
但是现存几个点待确认: 1.是否默认需要启用清理任务,降低使用。 2.默认清理日期设置为凌晨三点是否符合业务场景 3.设计每天清理一次,且在凌晨3点是银行的业务逻辑,是否符合其他行业。
银行核心业务历史数据清理的配置是每天清理一次,清理时间在3点。
其他现状调研: Apollo默认未开启自动清理, Etcd默认配置下 未启用自动压缩历史
主要修正了: 1.新增了清理任务的开关 2.支持定义启动时间,借鉴银行核心清理逻辑,设定为一天清理一次,避免大量10分钟清理的无效调用 3.优化清理调用方的选择逻辑,改为选择leader进行。
代码调用过程如下 ┌──────────────────────────┐ │ HistoryCleanupTask │ └──────────┬───────────────┘ │ ① 判断是否为 Leader ▼ ┌──────────────────────────┐ │ MemberManager.hasLeadership │ └──────────┬───────────────┘ │ (仅当为 Leader 时继续) ▼ ┌──────────────────────────┐ │ CleanupExecutor │ │ - 计算 cutoffTime │ │ - 循环 DELETE LIMIT 1k │ └──────────┬───────────────┘ │ ② 分批删除 ▼ ┌──────────────────────────┐ │ his_config_info 表 │ │ (历史配置数据仓库) │ └──────────────────────────┘
- 我理解可以新增清理任务的开关,现在已经有自定义保留天数的功能了,PR见 https://github.com/alibaba/nacos/pull/12367
- 定时任务10分钟调度一次的频率是不是还好啊,不过可以考虑将清理历史配置的定时任务间隔设置通过 HistoryConfigCleaner 这个 SPI 接口进行定义。这样要是用户有特殊需求,自行定义该时间间隔,默认情况继续保持 10 分钟
- 如果采用外置存储模式,还是使用 Raft 协议进行集群中的同步吗?
看完方案有几个问题:
- 清理任务的配置保存在哪? 是保存在application.properties吗?
- 加入Raft选主让主节点进行清理是否是好的方案,如此就强依赖Raft了, 本来我使用外置数据库不需要Raft的, 现在强依赖会不会导致稳定性的下降。
- 和数据源插件之间的协作关系是什么样的? 方案中没有透出这个点, 我理解应该和数据源插件是解耦合的,和现在应该是类似的。