为了账号安全,请及时绑定邮箱和手机立即绑定

Redis加MongoDB加Quartz做定时任务统计

标签:
Java MongoDB Redis

需求:每过一段时间统计一次目标调用次数,做成折线图的形式。redis做计数,写入mongoDB中。redis的key以天为单位,value递增,每五分钟存入mongoDB一次。
1,define redis key

    public static String getCallBaiDuTTSKey(String time) {
        return String .format("BaiDuTTSCount:%s:",time);
    }

2, get redis key

String baiduTtsRedisKey = RedisKeyCenter.getCallBaiDuTTSKey(LocalDate.now().toString());

3, key increment and set expire time

 redisService.incrementKey(baiduTtsRedisKey, 1);
 redisService.expire(baiduTtsRedisKey, 24, TimeUnit.HOURS);

4, core quartz task code

 @Override
    public void updateCallTtsCount() {
        String baiduTtsRedisKey = RedisKeyCenter.getCallBaiDuTTSKey(LocalDate.now().toString());
        // query from Redis
        Integer baiduCount = redisService.get(baiduTtsRedisKey, Integer.class);
        baiduCount = baiduCount == null ? 0 : baiduCount;
        
        // save into MongoDB
        CallTtsCountPO callTtsCountPO = new CallTtsCountPO();
        callTtsCountPO.setQueryTime(LocalDateTime.now());
        callTtsCountPO.setBaiduCount(baiduCount);
        mongoTemplate.save(callTtsCountPO);
    }

5, LoggedJob sub class

public class UpdateCallTtsCountQuartzJob extends LoggedJob {

    @Resource
    private TtsService ttsService;

    @Override
    protected void executeInternalLogged(JobExecutionContext jobExecutionContext) {
        ttsService.updateCallTtsCount();
    }

}

LoggedJob

public abstract class LoggedJob extends QuartzJobBean {

    private Class clazz = this.getClass();
    protected final Logger logger = LoggerFactory.getLogger(clazz);

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) {
        NewMDCDecoratorRunnable runnable = new NewMDCDecoratorRunnable(() -> {
            String fireInstanceId = jobExecutionContext.getFireInstanceId();
            logger.debug("定时任务开始执行, instanceId={}", fireInstanceId);
            try {
                executeInternalLogged(jobExecutionContext);
            } catch (Exception e) {
                logger.error("定时任务执行失败, instanceId={}", fireInstanceId, e);
            }
            logger.debug("定时任务执行完成, instanceId={}", fireInstanceId);
        });
        runnable.run();
    }

    protected abstract void executeInternalLogged(JobExecutionContext jobExecutionContext);
}

6, task config

/**
 * 定时任务配置
 */
@Configuration
public class QuartzConfig {

    @Resource
    private DataSource engineMasterDataSource;

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("triggers") Trigger[] triggers,
                                                     JobFactory jobFactory, MySpringBeanJobFactory mySpringBeanJobFactory,
                                                     PlatformTransactionManager transactionManager) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();

        // this allows to update triggers in DB when updating settings in config file:
        // 用于quartz集群,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
        factory.setOverwriteExistingJobs(true);
        factory.setJobFactory(mySpringBeanJobFactory);
        // 用于quartz集群,加载quartz数据源
        factory.setDataSource(engineMasterDataSource);
        // QuartzScheduler 延时启动,应用启动完10秒后 QuartzScheduler 再启动
        factory.setStartupDelay(10);
        factory.setJobFactory(jobFactory);
        factory.setApplicationContextSchedulerContextKey("applicationContext");
        // 注册触发器
        factory.setTriggers(triggers);
        factory.setTransactionManager(transactionManager);
        factory.setTaskExecutor(new ThreadPoolExecutor(10, 100, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200)));
        // 直接使用配置文件
        factory.setConfigLocation(new FileSystemResource(this.getClass().getResource("/quartz.properties").getPath()));
        factory.setWaitForJobsToCompleteOnShutdown(true);

        return factory;
    }

    /**
     * 加载触发器
     */
    @Bean(name = "triggers")
    public Trigger[] loadJobTriggers() throws ParseException {
        List<Trigger> triggerList = new ArrayList<>();

        if (!ApplicationConstant.CURR_ENV.isLocalization()) {
         // 
        triggerList.add(createTrigger(UpdateCallTtsCountQuartzJob.class, "0 0/5 * * * ?"));
        return triggerList.toArray(new Trigger[triggerList.size()]);
    }

    /**
     * 创建触发器工厂
     */
    private static Trigger createTrigger(Class<?> jobClass, String cronExpression) throws ParseException {
        // 创建JobDetail
        JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
        jobDetailFactoryBean.setJobClass((Class<? extends Job>) jobClass);
        jobDetailFactoryBean.setName(jobClass.getSimpleName());
        jobDetailFactoryBean.setDurability(true);
        jobDetailFactoryBean.setRequestsRecovery(true);
        jobDetailFactoryBean.afterPropertiesSet();
        JobDetail jobDetail = jobDetailFactoryBean.getObject();

        // 创建触发器CronTrigger
        CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
        factoryBean.setJobDetail(jobDetail);
        factoryBean.setName(jobClass.getSimpleName());
        factoryBean.setCronExpression(cronExpression);
        factoryBean.afterPropertiesSet();
        return factoryBean.getObject();
    }
}

7, mongo query entity

@Data
@Document(collection = CallTtsCountPO.COLLECTION_NAME)
public class CallTtsCountPO {

    public final static String COLLECTION_NAME = "TTS_CALL_COUNT";
    public final static String TIME_COLUMN_NAME = "queryTime";

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Indexed(name = "query_time_idx")
    private LocalDateTime queryTime;
    private Integer baiduCount;
}

8, query count list message

    @Override
    public List<CallTtsCountPO> getCallTtsCountType(LocalDateTime startTime, LocalDateTime endTime) {
        // default query
        if (Objects.isNull(startTime) && Objects.isNull(endTime)) {
            startTime = LocalDateTime.now().minusDays(7);
            endTime = LocalDateTime.now();
        }
        List<AggregationOperation> aggregationOperationList = new ArrayList<>();
        if (startTime != null) {
            aggregationOperationList.add(Aggregation.match(Criteria.where(CallTtsCountPO.TIME_COLUMN_NAME).gte(startTime)));
        }
        if (endTime != null) {
            aggregationOperationList.add(Aggregation.match(Criteria.where(CallTtsCountPO.TIME_COLUMN_NAME).lte(endTime)));
        }
        Aggregation aggregation = Aggregation.newAggregation(aggregationOperationList);
        return mongoTemplate.aggregate(aggregation, CallTtsCountPO.COLLECTION_NAME, CallTtsCountPO.class).getMappedResults();
    }

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
11
获赞与收藏
107

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消