并行执行组件(进程版)
2026/8/8 11:19:45 网站建设 项目流程

​背景

物资系统”物资库存”导出功能,导出的数据几千条上万条,耗时非常长,经分析,导出前端主导,前端一页一页地获取,全部获取完成后,前端生成xlsx文件。

设计有两个问题,1, 分页大小100,几千条数据前后端来回几十次;2,数据全部放在浏览器,用户内存使用造成压力

本文介绍大数据量处理性能优化方案,引入进程内的并行执行组件,多线程分片并行执行,支持数据量少降级到单线程,减少消耗;支持进度反馈;使用磁盘文件,支持百万数据导出

本组件是进程内的分片并行,若分布式的并行执行,支持几十上百节点大规模计算,需引入zookeeper

并行执行组件

组件使用ExecutorService和CountDownLatch,实现多线程并行,支持平均分片策略,支持进度实时反馈

开发示例

本节以物资系统的”物资库存”为例,介绍并行组件开发和使用,整个过程分3个阶段,

0 准备

  1. 首先设置线程数量,实际根据数据量和系统负载计算合适的线程数
  2. 生成uuid,返回给前端,后续前端带上uuid查询进度,下载文件
  3. 执行状态缓存,两种方式,本地map;分布式redis,前者在集群环境要考虑session亲和,uuid哈希,但健壮性不好,如,节点下线或者增加节点都会出问题,推荐使用redis,更新进度closure需要原子操作,可以使用lua或者getAndSet的原子操作,保证进度在多线程下正确更新

上图准备写入文档

1 导出任务

上图构建进度闭包类,执行中任务的线程各自累加完成量,计算出进度

上图是分片执行体,整个需要使用executor异步执行,因为ShardingExecutor使用LatchCountDown阻塞等待所有执行线程。

构建和初始化执行器,安全上下文,业务处理可能需要用到用户信息,权限信息等,手动传递上下文,如果使用了inherited线程本地变量可自动传递

业务逻辑实现为Consumer,接收分片,即,total根据平均分片,业务方法getPage自行解释,可以是0~n,也可以是a-c等等

数据处理完毕,进度inc更新进度,方法需要线程安全,可以使用AtomicLong之类的保证

上图是进度闭包的简单实现

2 定时获取进度;

前端打开任务后,带上uuid,定时调用获取进度

3 下载

客户端使用UUID下载文件

X 定时清理任务

服务端实现定时清理任务,根据任务超时时间和进度清理,这是全局的,若不需支持进度反馈,合并上面1,2,3为一个方法,并在最后清理,不需要全局的清理任务。

Benchmark

模拟服务端导出列表,包括写入excel文件,数据量使用过滤ISSUEUNIT字段控制

数据1000,线程数 1,3,10

数据数/线程数

1

3

10

1267

1.77/1.85/1.75

1.80/1.70/1.68

1.77/1.69

*以上统计连续跑3次,小数点后第三位不为0进一,单位:秒,下同

数据4000,线程数 1,3,5,10

数据数/线程数

1

3

5

10

4000

4.23/3.53/3.46

2.67/2.40/2.33

2.24/2.15/2.03

2.76/2.10/2.36

数据20000,线程数 5,10,20

数据数/线程数

5

10

20

24168

5.70/5.46/5.47

4.45/4.63/4.53

4.88/4.21/4.41

数据40000,线程数 5,10,20,30

数据数/线程数

5

10

20

30

42710

11.95/10.84/10.37

7.39/7.38

6.93/6.69

6.30/6.25

以上测试在IDE执行,jar包jdk服务模式运行性能会好些

总结:数据量越大,线程数多性能好,反之,数据量少,线程少性能好或者区别不大

NEXT

优化:可重置可复用的线程池,降低线程构建和销毁的消耗

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询