分布式环境下的分片数据导出方法

  最近提交了一个专利,是基于去年做的一个异步数据导出的项目,平稳支撑了16/17年的双十一,抽时间把其中的细节分享出来

  • 背景 

  数据导出excel的传统方法一般都是先将数据生成到内存中,然后利用excel的一些工具类生成excel文件通过http请求或者ftp返回给用户。但是在数据量很大或者并发量很高的场景中,往往会导致内存飙高或者频繁的FullGC,严重时会导致宕机。如果分批进行导出则导出数据量的大小与用户等待时间成正比,用户体验较差。

  我们的初衷就是要解决数据导出造成的内存溢出。本文将介绍一种分布式的分片数据导出方法,解决了系统的内存压力,能支撑大数据量及高并发的数据导出,具有较高的效率及扩展性。

  • 现有方案比较
  1. 方案一:在一台机器中,一个请求使用多个线程进行导出,最终生成excel文件,提高数据导出的效率
  2. 方案二:将用户的查询语句分成多个可执行语句,进行分批导出,同时数据是分批发送给用户

  方案分析

  第一种方案中,虽然使用了多线程进行导出,但是数据最终还是需要在内存中转换生成excel文件,这样不能真正解决内存压力问题。

  第二种方案中,虽然解决了大数据量的内存问题,但是数据是分批输送给用户的,体验较差,同时不能解决高并发的问题,具有局限性。

  同时,现有的方案中,一般都是在一台机器上进行分批导出,本质上都用增加导出时间的方式来缓解内存压力,是一种用时间换空间的方式。用户需要等待较长的时间,体验较差。

  • 方案细节

  我们同样也是基于分治的思想,但是采用了分布式的解决方案,将一个大数据的导出分片并分成多个子任务在不同的机器上进行导出,并且数据存储为csv格式文件,可以以追加的方式进行存储  

  希望达到的技术效果:

  1. 解决单点导出的内存压力
  2. 提高导出效率,用户不用等待太久
  3. 具有较高的扩展性,可以不断地提高导出的并发度及数据量

  

  方案实现

  一方面,数据量很大的情况下,不能将数据全部缓存在内存中,需要分片进行导出;另一方面并发量很大时,一台机器也不能满足需求,需要在分布式环境下分散每台机器的压力,这样就拥有了良好的扩展性。

  这种分片及分布式的数据导出方法,用于解决大数据量或高并发场景下数据导出问题,能够减轻系统内存压力,同时具有良好的扩展性。

  总体流程如下:

     分布式环境下的分片数据导出方法

 

  1. 第一步:用户向业务系统发出导出http请求;
  2. 第二步:业务系统向导出系统发起一个数据导出的RPC调用;
  3. 第三步:导出系统从各种存储系统(例如数据库、搜索等)中分片获取数据;
  4. 第四步:多台机器分片获取到的数据分别上传到文件存储系统中进行组合;
  5. 第五步:在文件系统中组合成csv文件;
  6. 第六步:用户从文件系统中下载文件;

   

  分布式分片导出方法: 

  分布式环境下的分片数据导出方法

  说明

  1. 首先主任务将数据分片,每个分片是一个子任务;
  2. 将所有子任务分发到不同的机器去并行执行,每台机器可以限制并行的子任务数量,来保证内存压力在可空范围。
  3. 当每台机器的子任务都达到阈值上限之后就会将任务缓存在主任务的阻塞队列中,直到所有任务分发完毕。
  4. 每个子任务拼装当前需要处理的数据,我们并不关心数据从哪里获取,可以从DB、搜索、Hbase等存储获取,同时可以在子任务中处理业务逻辑。然后将处理完的数据上传至文件存储系统中。
  5. 当所有子任务执行完毕之后主任务会向文件存储系统发送请求,将所有的分片合并成csv文件。此时主任务会更新任务状态并获取到文件下载链接。
  • 总结

  这种数据导出架构的核心思想有4个:

  1. 数据导出异步化,先用时间换空间
  2. 一个高并发及大数据量场景下的导出可以分而治之,分散内存压力
  3. 子任务(数据分片)分发到不同的机器,一方面分布式环境下均衡内存压力,另一方面用空间换时间
  4. 导出的数据文件可追加,基于流式化的导出