项目纪实-大Excel解析设计
使用Excel表格可以一次性导入大量数据,而页面的编辑需要逐条录入。对于需要导入大批量的数据时,使用Excel表格可以提高效率并且减少错误。所以在实际的项目中EXCEL导入的功能也是被大量采用。
需求、设计
需求
当前公司在接入一家医院后,需要将该医院的耗材资质数据导入到我们的管理平台。步骤如下:
- 在我们平台上下载EXCEL模版;
- 由实施人员根据院内耗材资质信息进行EXCEL模版的数据填写;
- 使用平台上的EXCEL导入功能,将填写完整的EXCEL表格上传到管理平台;
- 平台解析EXCEL表格,校验数据并导入数据库;
设计
对于我们程序猿来说,我们的关注点是在下载EXCEL模版、EXCEL导入、EXCEL解析、数据存到数据库等这些与程序相关的步骤。那么我们来逐个分析下这些功能的实现:
下载EXCEL模版:这个功能相对来说是比较简单的,最常用的就是讲一个空的EXCEL表格上传的oss资源服务器上,在提供一个下载接口,将oss上的EXCEL文件返回给客户端即可;EXCEL的导入、解析:导入就是文件的上传,就不多讲了。EXCEL的解析呢,一般来说都是使用的开源POI工具包,除此之外还有阿里的easyexcle、基于poi 封装的easypoi项目、hutool 工具包。数据入库:将解析EXCEL文件得到的数据存入数据库中。使用第三方的仓库层框架,如mybatis、jpa等。
以上就是一个使用EXCEL导入数据的完整流程以及所涉及到的功能点分析。
我们根据上边的分析来看,设计一个EXCEL文件导入功能,其实并不是很困难。但是以上分析是在 与其他需求不存在关联、忽略数据量、只考虑了EXCEL文件导入的情况下来进行设计的,如果我们加上一些需求再来看:
- 校验每个值是否符合平台数据字典的规则?
- 导入数据是否有重复?
- 导入的数据对应的资质证件是否有效?
- 导入的数据对应的资质证件是否在平台上已经存在了?
- 导入数据出现异常怎样处理?
- 多个人员在操作导入操作时怎么处理?
- …
这样一来,在数据量较大的情况下,每添加一个相关的需求,程序的执行性能就会成指数级的下降,因为每个数据都要走一遍这些规则。那我们该如何处理呢?
既然有问题,就有解决问题的方法。解决方案:数据分片 + 并发处理 + 缓存 + 异常处理
数据分片
一个EXCEL文件的数据量比较大时,我们可以将一个EXCEL文件拆分成多个EXCEL文件,将数据平分在每个EXCEL文件中,这就完整了EXCEL的数据分片。
并发处理
在处理大数据、多任务等等情况下,使用并发编程来提供程序的性能,是我们的不二只选。处理大数据量的EXCEL亦是如此。
线程池
当我们的接口收到上传的EXCEL文件时,就将其封装成一个解析任务,丢到线程池中执行。
解析EXCEL文件时使用线程池,有以下几个好处:
- 复用线程资源,避免由线程创建、销毁带来的性能消耗。
- 隔离解析任务,避免每个任务之间的相互影响。
- 隔离整个解析任务锁使用的CPU资源,避免由于解析EXCEL文件占用了服务器的大量CPU资源,影响到其它接口的性能情况。
生产消费模型
当我们使用POI解析EXCEL文件时,poi会将整个EXCEL文件中的数据加载到内存中,在大量的EXCEL文件同时进行解析时,极易发生OOM异常。
解决方案有两种:
- poi 官方提供的 SAX 事件驱动模型;
- 使用阿里开源的 easyexcel;
上边两种方式都解决的内存占用过大的问题,下边就是使用这些框架来解析excel文件拿到其中的数据。
将每个excel解析的数据,先上传到一个数据队列中,新建一个线程池,这个线程池负责消费队列中的数据。
消费线程池完成两个任务:
- 对数据进行校验
- 将校验通过或失败的数据存储到redis缓存中
上诉的过程其实就是一个典型的生产消费者模型,就数据的解析和数据校验分开,实现异步同时执行。
- 标题: 项目纪实-大Excel解析设计
- 作者: Heer Liu
- 创建于: 2020-10-23 20:55:10
- 链接: https://blog.heer.love/posts/ac7ff69a/
- 版权声明 : 本文章采用 CC BY-NC-SA 4.0 进行许可。