动态配置热更新无重启实现

摘要

代拍系统资费、页面配置、风控阈值、第三方接口密钥均存储动态配置,传统修改配置需重启服务,会造成业务短暂中断。本文基于 Spring 事件监听 + Redis 缓存实现配置热更新,修改后台参数后服务无需重启即时生效,附带监听核心代码,bidfans 全部业务动态配置采用该热更新方案。

一、配置重启更新的业务痛点

调整物流价格、服务费比例、风控出价阈值时,重启服务会中断竞拍、下单流程,高峰期重启会造成用户操作失败;多节点集群部署时,逐个重启同步配置效率极低;频繁发布小配置变更增加运维部署工作量。 热更新机制分为三层:数据库持久存储、Redis 全局缓存、内存配置 Bean,修改配置后主动清理缓存,内存 Bean 自动刷新,全程无需重启应用进程。

三、配置热更新监听核心代码

复制代码
@Component
public class ConfigRefreshListener {
    @Autowired private RedisTemplate<String,Object> redisTemplate;
    @Autowired private GlobalConfigHolder configHolder;
    // 监听配置更新事件
    @EventListener(ConfigUpdateEvent.class)
    public void onConfigUpdate(ConfigUpdateEvent event) {
        // 清理对应分类缓存
        String cacheKey = "config:" + event.getConfigType();
        redisTemplate.delete(cacheKey);
        // 重新加载配置至内存容器
        List<ConfigDO> newConfigList = configMapper.selectByType(event.getConfigType());
        configHolder.refreshConfig(event.getConfigType(), newConfigList);
    }
}
// 全局内存配置容器,业务直接读取内存数据
public class GlobalConfigHolder {
    private final Map<String,List<ConfigDO>> configMap = new ConcurrentHashMap<>();
    public void refreshConfig(String type, List<ConfigDO> list) {
        configMap.put(type, list);
    }
    public List<ConfigDO> getConfig(String type) {
        return configMap.getOrDefault(type, Collections.emptyList());
    }
}

后台提交配置修改后发布 Spring 事件,自动触发缓存清理与内存刷新,所有业务接口读取内存容器最新配置。

三、集群多节点同步方案

单节点修改配置后,通过 Redis 发布订阅通道推送更新事件,集群所有节点同步清理缓存、刷新内存配置,多节点配置数据实时统一,无需逐个重启。区分全局配置、计费配置、页面配置三类事件,仅刷新对应分类数据,不影响其他配置内存缓存。 bidfans 线上 4 节点集群,调整资费、首页楼层配置无需停机重启,配置生效延迟控制在 1 秒内。

四、配置变更日志追溯

每一次配置修改记录操作人、修改前后参数、修改时间,永久存储配置变更日志。运营可回溯任意历史配置数值,对账、故障排查时可还原历史资费标准,解决配置变更后无法追溯历史规则的问题。

结语

基于事件监听与 Redis 发布订阅的配置热更新方案,实现参数修改无服务重启即时生效,适配集群多节点同步需求,大幅降低配置变更运维成本,适合需要频繁调整业务规则的跨境代拍平台。