IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 大批量数据导出优化 -> 正文阅读

[系统运维]大批量数据导出优化

问题产生背景

用户操作导出明细账等大批量数据导出时,导致线上OOM频繁发生
通过分析内存快照可以发现,POI的对象以及相关的XML对象占用了绝大部分的内存消耗,由于导出的数据比较大量,后台直接用XSSFWorkbook导出,在导出结束前内存有大量的Row,Cell,Style等,以及基于XLSX底层存储的XML对象没有被释放,频繁GC无果最终导致内存溢出。

原因分析

  1. 从服务本身实现来看
    导出服务占用大量内存通常在这两个阶段:
    1. 首先,通过sql大批量查询,使用对象接收时会创建大量的对象从而占用大量内存资源;
    2. 其次,数据对象转化为POI对象XSSFWorkbook时,创建大量Row\Cell 对象,进一步加大内存压力。
  2. 从用户操作来看
    通常系统在判断可能需要大量数据导出时,通常会创建新的线程来执行异步导出任务,并且立即给予用户异步导出的提示,但用户可能在导出期间重复点击导出按钮,从而创建大量重复的导出任务浪费系统资源。
  3. 不规范的线程池创建
    虽然异步的导出任务使用了线程池,但是大多数情况下没有太多实际意义。线程池虽能提高线程的复用性和限制开辟大量多线程,但是前提应该建立在一组服务的线程出口应该仅使用一个线程池对象,而不应该每一个Service都创建一个线程池,不仅复用性低,并且使用new CachedThreadPool这种方式起不到约束线程总量的作用。

优化思路

  1. 限制导出服务开辟线程总量,通过适当长度的阻塞队列排队导出,来稳定系统压力

    通常用户在进行大批量数据导出时,对导出耗时并不会有苛刻要求(事实证明后边的优化不仅没有增加导出时间,反而大幅提升导出效率)

  2. 自定义分布锁控制,对特定需要限制用户重复操作的接口,通过同步锁来进行限制

  3. 使用高版本 SXSSFWorkbook 替代低版本 XSSFWorkbook

    通过显示指定窗口大小,超出窗口则进行落盘,从而减少内存占用

  4. 对于DB查询步骤,使用 ResultHandler 来实现数据对象的即时处理,可以大幅提升内存使用效率(自测百万数据量的情况下,结合SXSSFWorkbook 在导出过程中仅占用 100M以内的内存)

详细优化步骤

  1. 全局线程池

FinanceGlobalExportThreadPool.java
image.png
通过枚举类来创建单例线程池实例,每一个线程池实例核心线程为8,阻塞队列长度为16,总的最大线程数限制为32
FinanceGlobalExportThreadPoolDecorator.java
image.png
通过简单的包装类持有线程池,对submit过程包装异常,透出友好的任务拒绝信息
BooksExportService.java
image.png
image.png
线程池使用及声明

  1. 通过锁控制单一用户并发操作

ConcurrentLock
image.png
自定义注解,用于标注导出方法
ConcurrentLockAspect
image.png
切面逻辑:对于用户首次操作,使用keyPrefix + 企业ID + 用户ID 为key上锁,在失效时间内,当用户再次操作,会给出请勿频繁操作提示(注意,并没有主动通过remove方法去释放锁,而是采用失效时间,因为切面无法判断异步导出何时完成,所以无法主动去释放锁)
exportSubsidiaryLedgerList3
image.png
在方法上声明@ConcurrentLock 注解

  1. SXSSFWorkbook

对原有 ExcelExportUtil2 的exportToBytes方法中,替换一系列XSSFXXX为SXSSFXXX,并且添加刷盘、适配等操作,并且并没有改动原有的类,新的工具类:SxssExportUtil
仅在明细帐导出中使用新的工具类,预计线上运行无误后,逐步可进行其他导出的替换
image.png
image.png

测试

为了确保线上稳定性,仅对明细帐进行优化
下面是测试环境进行的导出测试,因为测试环境明细帐数据很少,所以将导出过程_creatDataBody_进行循环调用来模拟大批量数据导出,实验结果将证明,数据占用内存一定的情况下,不同POI类所使用的内存量
测试环境jvm配置为 -Xmx512M
image.png

  1. 首先使用旧的ExcelExportUtil2工具类,模拟22w数据量进行导出 (1490 * 150 = 223500 )

image.png
导出任务执行后,不出意外出现了OOM
在这里插入图片描述

  1. 使用新版本API的工具类 SxssExportUtil

直接构建 1490 * 700 约等于 1,040,000 百万数据量进行导出测试
image.png
明细帐导出成功!
在这里插入图片描述

查看文件详情
image.png
数据总量:
image.png
文件大小约33.9M 导出数据量 1043003 条
需要注意的是:EXCEL 2007 单Sheet数据总量限制为 1048576 ,超出此范围需要把剩余数据放到新的Sheet中

结论及建议

结论:
SXSSF是xssf的一个与API兼容的流媒体扩展,在必须生成非常大的电子表格且堆空间有限时使用,通过限制对滑动窗口中的行的访问来实现其低内存占用,而XSSF允许访问文档中的所有行。
SXSSF在使用中可以通过新的SXSSFWorkbook(int windowSize)指定工作簿构建时的窗口大小,默认为100行,即表示当行数达到101时,rownum=0的行被刷新到磁盘并从内存中删除,当rownum达到102时,rownum=1的行被刷新,以此类推。

可以看出,切换为SXSSF可以使导出过程使用较低的内存,但是它也有局限性

  1. 列宽无法根据所有数据行来调整(已使用最低宽度来解决样式问题)

image.png

  1. 注意显示调用workbook.dispose_()_;来清理临时文件

image.png
建议:
通过切换底层导出方式,可以极大缓解数据转换POI对象内存占用过高的问题,但是数据查询过程中JAVA ORM对象的内存占用仍然没能解决。
因为旧有的导出实现中,我们将数据和导出过程没有解耦合:必须将所有数据查询之后,再转交给工具类去转换导出,这样就不可避免的申请大内存来存储。
其实对于简单的导出场景:查询数据-> 转换导出 完全可以实现为:建立工作表 -> 查询数据过程中,同时进行Row以及Cell的创建-> 结束导出,使用此种方式,org.apache.ibatis.session.ResultHandler就有了用武之地,通过此接口,可以流式的将数据查询出来,在回调中边查询边处理,每次处理方法结束,便可以释放掉对象便于GC回收,实测 SXSSF + 流失查询,百万数据导出过程中,内存占用仅为100M以内
image.png
image.png
jvm启动内存为128m
image.png
从统计图上可以看到,内存维持在80M左右

参考文档

SXSSF (Streaming Usermodel API)
Excel大批量数据的导入和导出,如何做优化?
POI多线程分表导出百万级大数据量EXCEL导出

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 23:03:00  更:2022-03-10 23:03:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 3:36:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码