做项目我们经常会遇到的一个需求就是:导出
而当数据较多时,导出又会时常出现OOM,甚至引发雪崩连锁效应,不巧的是我们前段时间正在生产经历这种问题:单月百万左右订单,微服务架构,导出订单这个功能正巧落在订单服务,然后因此次导出导致OOM,继而出现雪崩,依赖的服务相继“跪下”了,现场情况大致如下
下面看看如何在有限的内存中导出大量的数据
面临问题:
????????1. 同步导出容易接口超时(读超时)
????????2. 同步导出容易OOM(数据量太大)
????????3. 数据量太大 或 SQL不精简导致慢
????????4. 业务需求:数据需要聚合 或 相同商品放在一起 或 按某些规则排序
????????5. 如果是异步,用户怎么拿到数据
????????6. excel太大,用户打不开咋整
如何实现:
????????异步导出、使用easyExcel、分页查询数据、计算limit起始位置、Mysql断点续传(少量多次)、文件上传到OSS、使用websocket通知 或 生成导出记录用户主动回查、多个sheet、总条数可配置、去掉count查询、order by 商品,聚合等业务处理
基于上面几个问题,学习下此方案里面的业务流程:
????????1. 异步导出
????????????????使用job记录 或 MQ 或 异步业务处理
????????2. 使用easyExcel
????????????????相比poi jxl来说更加省内存(具体有待验证)
????????3. 分页查询
????????????????可以采用分页,也可以采用 断点续传,本质都是可以减少内存占用(mysql占用内存 加载到jvm中占用特别大)
????????4. 多个sheet页
????????????????单页支持1048576行数据,有的版本行数过多打不开
? ? ? ? ? ? ? ? 也可拆分为多个excel文件后再次压缩[Java-压缩方案对比-CSDN博客]
? ? ? ? ? ? ? ? 如业务允许也可导出为cvs文件
????????5. 计算起始页
????????????????如果是多个sheet页/多excel文件 则需要关心这个问题
????????6. 文件上传到OSS
????????????????一般建议将应用服务器和文件服务器分开,应用服务器需要更多的内存资源或者CPU资源,而文件服务器需要更多的磁盘资源。而且用应用服务器会占用很多的宽带资源
????????7. 通过websocket通知
????????????????一般项目中都集成了Msg模块(站内信),用来向用户推送消息
????????????????如果没有的话,可以做一个 通知表,记录标题 用户 附加地址 下载地址 阅读状态等信息
????????8. 总条数可配置
????????????????可以根据条件取小部分数据,业务有时候并没有必要取所有数据,节省资源
改造前流程:
改造后流程: