单点定时任务JDK从JDK1.5开始原生,提供ScheduledExecutorService代替TimerTask执行定时任务,可靠性好。publicclassSomeScheduledExecutorService{publicstaticvoidmain(String[]args){//创建一个总共有10个线程的任务队列ScheduledExecutorServicescheduledExecutorService=Executors.newScheduledThreadPool(10);//执行任务:1秒后开始,每30秒执行一次秒);}}SpringTaskSpringFramework自带定时任务,提供cron表达式,用于实现丰富的定时任务配置。新手推荐使用https://img.ydisp.cn/news/20220902/mx35d4id2hp来匹配你的cron表达式。@Configuration@EnableSchedulingpublicclassSomeJob{privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(SomeJob.class);/***每分钟执行一次(eg:18:01:00,18:02:00)*第二分钟小时日月周年*/@Scheduled(cron="00/1***?*")publicvoidsomeTask(){//...}}单点定时服务在当前微服务环境下应用的场景越来越有限,我们来尝试一下分布式定时任务。基于Redis的实现与前面两种方式相比,这种基于Redis的实现可以通过多点增加定时任务,多点消费。但要做好防止双重消费的准备。通过ZSet方法:将定时任务存储在ZSet集合中,并将过期时间存储在ZSet的Score字段中,然后通过循环判断当前时间内是否有需要执行的定时任务,如果是,执行它。具体实现代码如下:/***描述:基于Redis的ZSet定时任务。
**@authormxy*@Date2020/8/2511:54*/@Configuration@EnableSchedulingpublicclassRedisJob{publicstaticfinalStringJOB_KEY="redis.job.task";privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(RedisJob.class);@AutowiredprivateStringRedisTemplatestringRedisTemplate;/***添加任务。**@paramtask*/publicvoidaddTask(Stringtask,Instantinstant){stringRedisTemplate.opsForZSet().add(JOB_KEY,task,instant.getEpochSecond());}/***定时任务队列消耗*每分钟一次(可以缩短间隔到1s)*/@Scheduled(cron="00/1***?*")publicvoiddoDelayQueue(){longnowSecond=Instant.now().getEpochSecond();//查询当前时间的所有任务Set
**@作者mxy*@Date2020/8/2512:07*/@ConfigurationpublicclassRedisExJob{@AutowiredprivateRedisConnectionFactoryredisConnectionFactory;@BeanpublicRedisMessageListenerContainerredisMessageListenerContainer(){RedisMessageListenerContainerredisMessageListenerContainerContainerContainerage=newListener呃();redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);返回redisMessageListenerContainer;}@BeanpublicKeyExpiredListenerkeyExpiredListener(){返回新的KeyExpiredListener(this.redisMessageListenerContainer());TOPIC_ALL_KEYEVENTS=newPatternTopic("__keyevent@*");基于redis的定时任务应用场景有限,实现起来比较简单,但是对功能的幂等性有很大的要求。从使用场景来说,应该叫延时任务。场景示例:下单15分钟后,如果用户没有付款,系统需要自动取消订单。红包24小时未验收,需要延迟退款。业务的优缺点是:被动触发,对服务资源消耗少RedisPub/Sub不可靠,没有ACK机制等,但一般来说,键空间通知功能会消耗一些CPU分布式定时任务引入分布式定时任务组件或中间件:将定时任务作为单独的服务来抑制重复消费,独立的服务也有利于扩展和维护。Quartz依赖于MySQL。使用起来比较简单,可以部署在多个节点上。它通过竞争数据库锁确保只有一个节点执行任务。没有图形化的管理页面,使用起来比较麻烦。elastic-job-lite依赖于Zookeeper,通过Zookeeper的注册和发现,可以动态添加服务器。多种作业模式、故障转移、运行状态收集、多线程数据处理、幂等容错处理、支持spring命名空间、图形化管理页面、LTS依赖Zookeeper、集群部署、可动态添加服务器。您可以手动添加计划任务、启动和暂停任务。业务日志记录器的SPI扩展支持故障转移节点监控各种任务的执行结果。支持FailStore容错和动态扩展。对春天比较友好。它具有用于监视和管理的图形界面。任务,支持横向扩展。您可以手动添加计划任务、启动和暂停任务。弹性扩展Shard广播故障转移滚动实时日志GLUE(支持在线代码编辑,无发布)任务进度监控任务依赖数据加密Email告警运行报告优雅宕机国际化(中文友好)总结微服务下,推荐使用xxl-job这一类组件服务合理有效地管理定时任务。单点定时任务有其局限性,适用于规模较小、对未来扩展要求不高的业务。相对而言,基于SpringTask的定时任务最简单、速度最快,而xxl-job的难点主要体现在集成和调试上。不管是哪种定时任务,都需要保证任务不会因为集群部署而被多次执行。任务异常将得到有效处理。任务处理太慢,导致大量积压。任务应该在预期的时间点执行。可以使用中间件。解耦服务,但增加了复杂性。
