Java 生产环境:分片执行、多线程并行异步导入导出、断点续传、失败重试实战全解
目录
一、核心概念与生产选型
1. 核心技术栈(企业标准)
2. 核心设计思路
二、生产级表结构设计(必须)
1. 总任务表 async_task
2. 任务分片表 async_task_slice
三、基础配置:线程池 + 异步
1. 线程池配置(生产关键,避免 OOM / 资源耗尽)
2. 重试机制配置(分片失败自动重试)
四、实战一:并行异步导出(大数据量无 OOM)
流程
1. 统一任务状态枚举
2. 核心:创建任务 + 自动分片
3. 多线程并行执行分片(核心)
五、实战二:并行异步导入(大文件解析)
流程
核心:异步解析 + 分片入库
六、实战三:断点续传 + 失败重试(生产灵魂功能)
1. 断点续传原理
2. 断点续传接口(前端可直接调用)
3. 失败重试机制(生产级)
七、生产环境必须注意的坑(避坑指南)
八、完整架构总结图
九、总结
这是企业级 Java 开发高频核心场景(Excel/CSV 大数据量导入导出),生产环境绝对不能用单线程同步执行,必须解决:
- 大文件 OOM
- 接口超时
- 任务卡死不可恢复
- 失败全量重来
- 并发安全 & 数据一致性
本文会用可直接落地生产的方案 + 代码 + 架构设计,完整讲透。
一、核心概念与生产选型
1. 核心技术栈(企业标准)
- 异步框架:Spring
@Async+ 自定义线程池(拒绝使用默认线程池) - 文件处理:Alibaba EasyExcel(无内存占用,业界标准)
- 任务管理:MySQL 任务表 + 分片表(记录进度、状态、分片)
- 重试机制:Spring Retry / Guava Retrying(异步任务专用)
- 断点续传:基于分片编号记录成功 / 失败状态,续传只跑失败分片
- 分片策略:按主键 ID 范围 / 页码 / 时间切分数据,避免重复 / 遗漏
2. 核心设计思路
- 任务表:存储总任务(文件名、状态、总条数、成功条数、失败原因)
- 分片表:把大任务切成 N 个小分片(独立状态、独立重试)
- 异步执行:线程池并行执行分片,不阻塞主线程
- 状态实时更新:执行中 / 成功 / 失败 / 暂停,前端可实时查进度
- 断点续传:重启服务 / 任务失败,只执行未完成 / 失败分片
- 失败重试:分片级重试,不影响其他分片,支持最大重试次数
二、生产级表结构设计(必须)
这是断点续传、失败重试、进度追踪的基础,直接复制到项目使用。
1. 总任务表async_task
CREATE TABLE `async_task` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务ID', `task_no` varchar(64) NOT NULL COMMENT '任务唯一编号', `task_type` varchar(32) NOT NULL COMMENT '任务类型:IMPORT/EXPORT', `file_name` varchar(255) DEFAULT NULL COMMENT '文件名', `file_url` varchar(512) DEFAULT NULL COMMENT '文件OSS地址', `total` int DEFAULT '0' COMMENT '总数据量', `success` int DEFAULT '0' COMMENT '成功数据量', `fail` int DEFAULT '0' COMMENT '失败数据量', `status` varchar(32) NOT NULL DEFAULT 'WAIT' COMMENT '状态:WAIT/RUNNING/SUCCESS/FAIL/PAUSE', `err_msg` text DEFAULT NULL COMMENT '错误信息', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_task_no` (`task_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='异步任务总表';2. 任务分片表async_task_slice
CREATE TABLE `async_task_slice` ( `id` bigint NOT NULL AUTO_INCREMENT, `task_no` varchar(64) NOT NULL COMMENT '任务编号', `slice_no` int NOT NULL COMMENT '分片编号 1,2,3...', `start_id` bigint NOT NULL COMMENT '起始主键ID', `end_id` bigint NOT NULL COMMENT '结束主键ID', `count` int DEFAULT '0' COMMENT '分片数据量', `status` varchar(32) DEFAULT 'WAIT' COMMENT 'WAIT/RUNNING/SUCCESS/FAIL', `retry_count` int DEFAULT '0' COMMENT '重试次数', `err_msg` text DEFAULT NULL COMMENT '错误信息', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_task_slice` (`task_no`,`slice_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='异步任务分片表';三、基础配置:线程池 + 异步
1. 线程池配置(生产关键,避免 OOM / 资源耗尽)
@Configuration @EnableAsync // 开启异步 public class ThreadPoolConfig { @Bean("asyncTaskExecutor") public Executor asyncTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心线程数:根据服务器CPU核心数设置(CPU核心*2 或 服务器配置酌情调整) executor.setCorePoolSize(10); // 最大线程数 executor.setMaxPoolSize(20); // 队列容量 executor.setQueueCapacity(100); // 空闲时间 executor.setKeepAliveSeconds(60); // 线程名前缀(方便日志排查) executor.setThreadNamePrefix("async-task-"); // 拒绝策略:由调用线程处理(避免任务丢失) executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }