You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

主从配置技术求助:生产环境主节点故障后数据同步异常

生产环境Ignite主从集群数据同步故障排查与解决

问题场景

3节点Ignite主从集群:1台主节点连接数据库同步数据,2台从节点同步主节点数据。主节点离线数分钟恢复后,未从数据库加载最新数据,反而同步了从节点的陈旧数据。

已尝试操作

  • 将主节点缓存重平衡模式设为NONE,从节点设为ASYNC
  • 通过代码ignite.services().deployClusterSingleton("DatabaseSyncService", new DatabaseSyncService(vertx, routerService, emiService))尝试动态主节点分配
  • 备份方案因主节点故障时数据库连接中断失效

故障原因分析

  1. Ignite默认集群数据同步逻辑优先从集群内节点拉取分区数据,主节点恢复时会优先同步从节点的陈旧数据,而非主动从数据库加载最新数据
  2. 缓存重平衡配置调整未针对主节点恢复后的数据源优先级做设置
  3. 集群单例服务未触发主节点恢复后的数据库全量同步逻辑

解决方案

1. 强制主节点启动时优先加载数据库数据

修改主节点缓存配置与启动逻辑,确保主节点完成数据库全量加载后再加入集群同步:

  • 主节点缓存配置保持CacheRebalanceMode.NONE,避免启动时拉取集群旧数据
  • 主节点启动完成后,手动执行数据库全量数据加载,再开启重平衡同步到从节点:
// 主节点启动后执行数据库全量数据加载
Cache<String, YourDataModel> cache = ignite.cache("target-cache");
List<YourDataModel> latestDbData = yourDbService.fetchAllLatestData();
cache.putAll(latestDbData.stream()
    .collect(Collectors.toMap(YourDataModel::getUniqueKey, Function.identity())));

// 加载完成后开启重平衡,同步最新数据到从节点
cache.configuration().setRebalanceMode(CacheRebalanceMode.ASYNC);
ignite.rebalance("target-cache");

2. 优化集群单例服务的触发逻辑

更新DatabaseSyncService,增加主节点恢复后的自动同步机制:

  • 在服务初始化时,判断当前节点是否为主节点,若是则立即触发数据库同步
  • 监听集群节点加入事件,当主节点恢复并加入集群时,自动执行数据刷新:
// 监听节点加入事件,触发主节点数据同步
ignite.events().localListen(event -> {
    if (event.type() == EventType.EVT_NODE_JOINED) {
        ClusterNode localNode = ignite.cluster().localNode();
        // 验证当前节点为主节点且是刚恢复的节点
        if (isDesignatedMaster(localNode) && event.node().id().equals(localNode.id())) {
            this.syncDbToCache(); // 自定义数据库到缓存的同步方法
        }
    }
    return true;
}, EventType.EVT_NODE_JOINED);

3. 配置主节点分区独占策略

通过缓存亲和性配置,确保主节点持有所有数据的主副本,避免恢复时从从节点拉取数据:

  • 调整缓存亲和性配置,让主节点独占主分区:
CacheConfiguration<String, YourDataModel> cacheCfg = new CacheConfiguration<>("target-cache");
// 设置主节点持有所有主分区,从节点仅存备份
cacheCfg.setAffinity(new RendezvousAffinityFunction(false, 1));
cacheCfg.setBackups(2); // 对应2台从节点的备份数量

4. 配合持久化优化数据加载顺序

若启用Ignite持久化,需确保主节点启动时用数据库数据覆盖本地持久化的陈旧数据:

  • 主节点启动前,清理本地持久化的旧数据目录,或在启动时执行数据库数据全量覆盖:
// 启动前清理持久化数据(需谨慎操作,仅主节点执行)
DataStorageConfiguration storageCfg = ignite.configuration().getDataStorageConfiguration();
File storageDir = new File(storageCfg.getStoragePath());
if (storageDir.exists()) {
    Files.walkFileTree(storageDir.toPath(), new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}

内容的提问来源于stack exchange,提问作者Kartikey Srivastava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:37:33