项目纪实-大Excel解析设计

Heer Liu

使用Excel表格可以一次性导入大量数据,而页面的编辑需要逐条录入。对于需要导入大批量的数据时,使用Excel表格可以提高效率并且减少错误。所以在实际的项目中EXCEL导入的功能也是被大量采用。

需求、设计

需求

当前公司在接入一家医院后,需要将该医院的耗材资质数据导入到我们的管理平台。步骤如下:

  1. 在我们平台上下载EXCEL模版;
  2. 由实施人员根据院内耗材资质信息进行EXCEL模版的数据填写;
  3. 使用平台上的EXCEL导入功能,将填写完整的EXCEL表格上传到管理平台;
  4. 平台解析EXCEL表格,校验数据并导入数据库;

设计

对于我们程序猿来说,我们的关注点是在下载EXCEL模版、EXCEL导入、EXCEL解析、数据存到数据库等这些与程序相关的步骤。那么我们来逐个分析下这些功能的实现:

  • 下载EXCEL模版:这个功能相对来说是比较简单的,最常用的就是讲一个空的EXCEL表格上传的oss资源服务器上,在提供一个下载接口,将oss上的EXCEL文件返回给客户端即可;

  • EXCEL的导入、解析:导入就是文件的上传,就不多讲了。EXCEL的解析呢,一般来说都是使用的开源POI工具包,除此之外还有阿里的easyexcle、基于poi 封装的easypoi 项目、hutool 工具包

  • 数据入库:将解析EXCEL文件得到的数据存入数据库中。使用第三方的仓库层框架,如mybatisjpa等。

以上就是一个使用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解析的数据,先上传到一个数据队列中,新建一个线程池,这个线程池负责消费队列中的数据。

消费线程池完成两个任务:

  1. 对数据进行校验
  2. 将校验通过或失败的数据存储到redis缓存中

上诉的过程其实就是一个典型的生产消费者模型,就数据的解析和数据校验分开,实现异步同时执行。

  • 标题: 项目纪实-大Excel解析设计
  • 作者: Heer Liu
  • 创建于: 2020-10-23 20:55:10
  • 链接: https://blog.heer.love/posts/ac7ff69a/
  • 版权声明 : 本文章采用 CC BY-NC-SA 4.0 进行许可。
推荐阅读
线程池 线程池 ShardingSphereJdbc 执行流程 ShardingSphereJdbc 执行流程 JVM - 类加载过程 JVM - 类加载过程