欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

记一次性能优化的艰苦历程

程序员文章站 2022-03-02 17:09:07
...

场景:系统A 每天会不定期往系统B 通过文件的形式输送大概200到300万的数据,B 系统需要首先解析文件拿到这些数据并存储到系统B 中,同时系统B 的定时任务还需要根据这批数据生成一批数据,并把数据在通过RocketMQ 推送到系统C 当中,当然生成数据和推送是分两个定时任务执行的,
遇到问题:首先开始需求没有说明白这个接口需要承接百万数据量,所以导致采用的普通的处理方式,效率极慢,压测时,百万数据长达1个小时处理,毫无疑问,直接呗测试打回,
解决方案: 准备从两个方向入手,第一线程池技术,第二数据库索引
第一 、线程池技术,
引入线程池技术,那么就需要注意线程安全问题了,此处我们不讨论线程安全,要创建一个线程池,我们此次使用的下面的线程池

    final static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 8, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(500), new ThreadPoolExecutor.CallerRunsPolicy());

首先我们要知道几个参数 ,核心线程数,总线程数,线程空闲时间,时间单位,队列初始化长度,拒绝策略
这个参数一般是根据服务器,JVM 的容量等参数经过计算出来的,不是说线程越多执行效率就越高,
我们此处设定3个核心线程数,8个总线程数,线程空闲时间 30 时间单位 秒,队列初始容量 500 ,这个值也是要经过计算的,我试过了,如果容量太大,会出现 java.util.concurrent.RejectedExecutionException
这个错误,所以大家不要随心所欲哦,当然这个错误是指你创建的线程太多的,导致队列都满了之后才会出现这样的问题。此处大家要处理了,那么创建了线程池,每个线程的数据量如何计算呢,我们此处采用的是 分页来处理,因为我们单纯的计算了一下,如果我们每个线程处理1000数据量来说,每个线程
两个容量是1000的集合,创建1000个对象,总共是3000 的容量,那么8个线程数,就是2万4 了,还有一些其属性等,2万多,我觉得还行,好接下来线程池这块就这么确定下来了,
分页处理,每批次1000,此时没有运用到索引,执行速度是54分钟,这个速度显然不合格呀,咋办呢,

第二点、数据库索引
首先给常用的字段建立组合索引,如那个会有模糊查询的字段单独建立一个索引,同时在书写sql 时,索引字段在前,非索引字段在后,模糊搜索在后,且如果模糊搜索字段和其他索引同时存在,只有模糊搜索字段的索引会起效果,此处需要注意,否则,恰当的索引可以极大的提高我们的执行效率,经过添加索引之后,加上多线程我们的执行效率有了一个质的飞越,时间来到了22分钟,因为我们对于时间要求咋30分钟内即可,所以基本算是完成了。
今天主要是把这个思路和方式方法记录下来,以后遇到了可以作为一个思路和启发吧