百万级数据导入导出优化总结
1、 背景
大家在日常的开发中,excel导入导出是非常常见的需求,大部分公司因为业务量比较小,操作的数据量都是几千、几万,这个级别的数据量,我们采用apache的POI很轻松可以搞定,但如果遇到大型互联网公司动不动就百万级别的用户体量,POI就会出现各种各样的问题,比较常见的现象就是内存OOM或者导入导出耗时特别久无响应,很显然,POI在百万级别的数据量处理,已经不合适了。
2、痛点
1、导入百万级别数据(excel)到DB,有什么痛点呢?
-
一次加载百万级别数据到内存,发生OOM?
-
导入时百万级别数据存储到DB如果循环一条条插入,数据库链接不够用?
2、导出百万级别数据(DB)到excel,有什么痛点?
-
一次查询百万级别数据到内存,mybatis查询超时报错?
-
一次加载百万级别数据到内存,发生OOM?
-
百万级别数据导出到Excel,写到一个Sheet中,能打开,不卡爆?
-
百万级别数据导出到Excel中一行一行写入Excel,频繁io操作,CPU飙高?
3、业务操作高峰期,后台管理员频繁操作导入导出excel,这个时候系统很容易就会因为内存溢出挂掉了
3、解决方案
1、选用合适的excel开源处理框架
阿里的easyexcel
2、百万级别导入方案
-
逐行解析excel数据,分批读取excel数据放到List, ist达到一定数据量持久化到DB,同时清空List列表数据;
-
采用mybatis的foreach批量保存、mybatis-plus批量saveBatch法保存;
3、百万级别导出方案
-
分批分页查询db数据到内存,比如一次查询5000条,分20次分批查询出来;
-
每次加载指定大小的数据到内存,比如每次5000条,5000条批量写入到excel以后,清空当前List,释放内存;
-
分多个sheet写入,每个sheet比如放20w,100百万数据放到5个sheet;
4、解决高峰期导入导出资源瓶颈
-
从产品侧设计的时候,引导产品,将导入导出功能设计成异步,尽量不要同步等待,虽然牺牲了一点体验,但是长期看对系统的稳定非常重要(为了产品的体验,可以提供一个统一excel导入导出历史记录功能给产品或运营同学,支持查看对应的下载进度,可追溯),异步导入导出可参考这里
-
前端导入导出按钮控制操作的频率,比如3分钟内不能频繁导入导出。
-
后端导入导出采用MQ异步排队处理,防止把内存写爆,CPU打满。
-
采用动态配置开关控制导入导出的数量,通过压测预估系统处理数据的阔值,导入导出超过闻值需要产品或运营发邮件申请,开发修改配置如果业务确实有超大数据量要求,超过闽值太多,引导产品或运营分批导入导出解决。
通过以上方法,能够有效的支撑百万级别的数据导入导出,而且系统的CPU、内存等核心指标不会出现明显波动。