前言
XXL-Job部署教程
项目中,必然少不了数据的导入导出,针对数据的导入导出简单复盘一下。
为了不占用资源消耗时间,影响用户体验,大量数据的导入导出一般都是异步执行
导入的时候,如果数据量很大,一次性全部读取到内存中,再去整体校验入库,会有OOM的风险
因此诞生了第二个方案,采用流分批读写,这样牺牲掉整体校验的需求,优化OOM问题。
但对于整个系统而言,整体内存资源有限,一个用户的导入导出可以满足,那很多的导入导出还是会造成OOM风险。
因此凡是涉及到异步的接口均要考虑任务调配的问题。
根据我们的经验,要进行合理的任务调配,有两套成熟的方案:
- 消息中间件,如kafka的生产消费者实现任务调度
- 分布式调用框架 quartz 、xxl-job也能实现任务调度
使用哪一套方案呢?
如果我们期待老王导出文件1和文件2,且将消息告诉小李和张姐,小李和张姐也导出导入文件1和文件2。这就是消息通信,这个场景下kafka是最合适的。如下这个场景
如果我们期待老王每天8点导出银行账单,小李每天9点导出金融界的新闻,张姐每天10点导入会议纪要,每个人在固定的时间干好自己的事情就行,这个场景下分布式调用框架最合适。
分布式框架是如何实现任务调度,能满足我们的需求吗?
原理这里就不展开解释了,确实在开发过程中,因为我们项目的数据量较大,每次导入导出都会及其消耗资源,为了方便管理,就需要模仿任务调度的设计,来管理我们的导入导出操作。
期待的最终效果是:机器资源有限,若大量的导入导出任务同时进行,封装的工具包会将这些任务管理起来,当资源空闲时,便执行任务,当资源紧缺时,先不执行异步任务。为了区分导入导出任务,自定义注解@AsyncTask表示这是一个异步导入导出任务。系统启动后,便会找到该注解,该注解对应的方法会被统一管理起来,类似一个Bean。然后根据通过计算系统资源的情况,在资源合适的情况下从线程池捞一条线程出来去执行这个方法,如果执行失败,该任务的优先级降低一级。达到一定阈值后,不会再自动执行该任务。此外对线程加一个乐观锁,避免多个线程操作同一个数据库造成事务不一致的问题。
若引入xxl-job,还需要维护此开源工具,成本较大,若基于kafka,若是使用我们这套工具,还必须部署kafka服务。因此,借鉴成熟开源项目,封装组件是有必要的。后续尝试一下