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

Apache Ignite加载千万数据遇GC溢出 调JVM参数后IDE崩溃求助

Apache Ignite批量加载1000万数据内存溢出问题解决方案

核心问题分析

8GB物理内存环境下,你当前的配置(堆内存4G + 堆外数据区6G)总内存需求远超系统可用内存,导致内存耗尽触发GC过载或系统崩溃。同时DataStreamer和缓存配置存在可优化点,进一步加剧内存压力。


1. 内存配置调整(关键)

JVM堆内存优化

将堆内存下调至2G,避免与Ignite堆外数据区争夺内存,同时改用G1GC更适合批量数据场景:

-Xms2g -Xmx2g -Xmn1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200

Ignite堆外数据区调整

将数据区最大容量从6G降至4.5G,预留至少1.5G给系统和JVM非堆内存:

regionCfg.setMaxSize(4831838208L); // 约4.5GB,计算方式:4.5*1024*1024*1024

2. DataStreamer写入优化

调整批量参数

开启批量写入优化,减少内存占用和网络开销:

public void streamBulkData(String cacheName, List<ProductLines> records) {
    try (IgniteDataStreamer<String, ProductLines> streamer = ignite.dataStreamer(cacheName)) {
        streamer.allowOverwrite(true);
        // 调整批量参数
        streamer.perNodeBufferSize(10240); // 单节点缓冲区大小
        streamer.perNodeParallelOperations(8); // 并行写入线程数
        streamer.autoFlushFrequency(500); // 自动刷新间隔(毫秒)

        for (ProductLines record : records) {
            String key = record.getPan_no();
            if (key != null) {
                streamer.addData(key, record);
            }
        }
        // 移除手动flush,DataStreamer会自动批量刷新
    } catch (CacheException e) {
        System.err.println("数据写入缓存失败: " + e.getMessage());
    }
}

控制并发写入

原代码串行处理但用runAsync可能导致线程堆积,改用固定线程池控制并发数:

// 初始化固定线程池(根据CPU核心数调整,比如4)
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(4);

public CompletableFuture<Void> processAllRecords() {
    long startTime = System.currentTimeMillis();
    int pageNumber = 0;
    Page<ProductLines> page;
    List<CompletableFuture<Void>> futures = new ArrayList<>();

    do {
        page = productLinesRepo.findRecordsWithPanNotNull(PageRequest.of(pageNumber++, BATCH_SIZE));
        List<ProductLines> records = page.getContent();
        if (!records.isEmpty()) {
            int finalPageNumber = pageNumber;
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                igniteCacheService.streamBulkData("poswavierCache", records);
                logger.info("已处理记录数: {}", (finalPageNumber - 1) * BATCH_SIZE + records.size());
            }, EXECUTOR);
            futures.add(future);
        }
    } while (page.hasNext());

    // 等待所有任务完成
    CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

    long endTime = System.currentTimeMillis();
    logger.info("总处理耗时: {} 毫秒", endTime - startTime);
    return CompletableFuture.completedFuture(null);
}

实体对象轻量化

将JPA实体ProductLines转为DTO对象,移除懒加载代理和不必要的关联字段,减少单条记录内存占用。


3. Ignite服务器配置修正

修正缓存泛型类型

缓存配置泛型与实际存储类型不匹配,修正后避免类型转换开销:

CacheConfiguration<String, ProductLines> marksCacheCfg = new CacheConfiguration<>();

调整缓存模式(可选)

如果业务不需要全量数据复制,将REPLICATED改为PARTITIONED模式,大幅降低单节点内存压力:

marksCacheCfg.setCacheMode(CacheMode.PARTITIONED);
marksCacheCfg.setBackups(1); // 根据需求设置备份数

关闭不必要的特性

生产环境关闭对等类加载,避免类加载内存泄漏:

cfg.setPeerClassLoadingEnabled(false);

4. 系统层面优化

  • 直接用命令行启动Ignite服务器,避免IDE占用额外内存;
  • Linux系统禁用swap分区,防止内存交换导致性能骤降和崩溃;
  • 确保磁盘有足够空间存储Ignite持久化数据。

内容的提问来源于stack exchange,提问作者Dude Ramasamy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:44:57