这是我参与 8 月更文挑战的第 6天,活动详情查看: 8月更文挑战
书接上文,具体可去查看redis生产环境如何干活,了解详细流程,现在我们已经将任务进行分析了,现在就一个问题,如何分析这个海量数据,根据上文的任务发布,拦截,进入指定的方法,然后分析。。。
如何尽可能完整的分析数据/
之所以用尽可能这个词是因为分布式项目很难做到对某些数据统计的准确性,只能尽可能的保证接近完整,首先初始化你的返回对象,我们采用加锁的串行的处理方式-->CountDownLatch(之所以前面批量处理,后面串行处理,因为我们觉得数据质量很重要,毕竟批量处理可以放到半夜执行,时间不是问题),简单介绍一下就是线程执行就给其计数器赋一个线程数,然后执行这其中包裹的逻辑,执行完成就减1,为0就执行完成表示所有的线程都已经完成一些任务,会让其他阻塞的线程走下面流程,所以CountDownLatch是执行完会给回收,下次会重新创建,还是刚刚说的,我们执行的是串行化的处理方式,所以我们的CountDownLatch初始化的值是1,这里说一下,之前我们已经将文件列表push到redis之中了,现在取出该请求
redisTemplate.opsForList().rightPop(currentRedisKey, 1, TimeUnit.SECONDS);
计数器执行模拟代码就是
CountDownLatch latch = new CountDownLatch(1);
//初始化规则处理类
UserMessPollHandle userMessPollHandle = new UserMessPollHandle(localResourcePath, taskExecutor, latch, ReportDTO);
//taskExecutor是初始化线程池new ThreadPoolTaskExecutor();
userMessPollHandle.executeData(taskExecutor);
latch.await();
对于UserMessPollHandle 我们在初始化的时候已经将需要的参数传了过来,现在在pollData中执行taskExecutor.submit(new UserMessProcessHandle(参数...) ),这里依然是死循环方式,不停地获取文件中每一行数据,执行解析,在submit中执行规则解析,这里是实现callable接口
public class UserMessProcessHandle implements Callable<Boolean> {
public Boolean call() {
//执行逻辑
}
}
执行完毕后会执行latch.await();,释放资源,走下面流程,至此,串行化分析逻辑结束
至此一个完整的请求,分发,多线程池化,串行化,分析完毕结束,真实的生产环境远不止 我写的如此,需要考虑很多场景,这里只是简述一下大概逻辑......,比如上面我们是串行化,某些可能是多任务同时处理,处理完成才走下面逻辑,不过记住,创建CountDownLatch的时候给的线程数不宜过多,毕竟创建销毁很浪费资源,在这里埋个坑,因为我们批量分析的时候,每次结果都不一样,为什么呢,虽然问题解决很简单,但是排查却用了半个月,我会在下篇说说为什么在多线程、加各种锁的情况下会出现线程不安全的行为;
干就完了,奥利给
好啦,今天的不开心就止于此吧,明天依旧光芒万丈发啊,宝贝!