游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

如何实现一个任务调度系统

  阅读一篇定时任务框架选型的文章时,一位网友的留言电到了我:
  我看过那么多所谓的教程,大部分都是教如何使用工具的,没有多少是教如何制作工具的,能教如何仿制工具的都已经是凤毛麟角,中国软件行业,缺的是真正可以制作工具的程序员,而绝对不缺那些使用工具的程序员!。。。。。。这个业界最不需要的就是会使用XX工具的工程师,而是有创造力的软件工程师!业界所有的饭碗,本质就是有创造力的软件工程师提供出来的啊!
  写这篇文章,想和大家从头到脚说说任务调度,希望大家读完之后,能够理解实现一个任务调度系统的核心逻辑。
  1Quartz
  Quartz是一款Java开源任务调度框架,也是很多Java工程师接触任务调度的起点。
  下图显示了任务调度的整体流程:
  Quartz的核心是三个组件。任务:Job用于表示被调度的任务;触发器:Trigger定义调度时间的元素,即按照什么时间规则去执行任务。一个Job可以被多个Trigger关联,但是一个Trigger只能关联一个Job;调度器:工厂类创建Scheduler,根据触发器定义的时间规则调度任务。
  上图代码中Quartz的JobStore是RAMJobStore,Trigger和Job存储在内存中。
  执行任务调度的核心类是QuartzSchedulerThread。
  调度线程从JobStore中获取需要执行的的触发器列表,并修改触发器的状态;Fire触发器,修改触发器信息(下次执行触发器的时间,以及触发器状态),并存储起来。最后创建具体的执行任务对象,通过worker线程池执行任务。
  接下来再聊聊Quartz的集群部署方案。
  Quartz的集群部署方案,需要针对不同的数据库类型(MySQL,ORACLE)在数据库实例上创建Quartz表,JobStore是:JobStoreSupport。
  这种方案是分布式的,没有负责集中管理的节点,而是利用数据库行级锁的方式来实现集群环境下的并发控制。
  scheduler实例在集群模式下首先获取{0}LOCKS表中的行锁,Mysql获取行锁的语句:
  {0}会替换为配置文件默认配置的QRTZ。schedname为应用集群的实例名,lockname就是行级锁名。Quartz主要有两个行级锁触发器访问锁(TRIGGERACCESS)和状态访问锁(STATEACCESS)。
  这个架构解决了任务的分布式调度问题,同一个任务只能有一个节点运行,其他节点将不执行任务,当碰到大量短任务时,各个节点频繁的竞争数据库锁,节点越多性能就会越差。2分布式锁模式
  Quartz的集群模式可以水平扩展,也可以分布式调度,但需要业务方在数据库中添加对应的表,有一定的强侵入性。
  有不少研发同学为了避免这种侵入性,也探索出分布式锁模式。
  业务场景:电商项目,用户下单后一段时间没有付款,系统就会在超时后关闭该订单。
  通常我们会做一个定时任务每两分钟来检查前半小时的订单,将没有付款的订单列表查询出来,然后对订单中的商品进行库存的恢复,然后将该订单设置为无效。
  我们使用SpringSchedule的方式做一个定时任务。Scheduled(cron02?)publicvoiddoTask(){log。info(定时任务启动);执行关闭订单的操作orderService。closeExpireUnpayOrders();log。info(定时任务结束);}
  在单服务器运行正常,考虑到高可用,业务量激增,架构会演进成集群模式,在同一时刻有多个服务执行一个定时任务,有可能会导致业务紊乱。
  解决方案是在任务执行的时候,使用Redis分布式锁来解决这类问题。Scheduled(cron02?)publicvoiddoTask(){log。info(定时任务启动);StringlockNamecloseExpireUnpayOrdersLock;RedisLockredisLockredisClient。getLock(lockName);尝试加锁,最多等待3秒,上锁以后5分钟自动解锁booleanlockedredisLock。tryLock(3,300,TimeUnit。SECONDS);if(!locked){log。info(没有获得分布式锁:{},lockName);return;}try{执行关闭订单的操作orderService。closeExpireUnpayOrders();}finally{redisLock。unlock();}log。info(定时任务结束);}
  Redis的读写性能极好,分布式锁也比Quartz数据库行级锁更轻量级。当然Redis锁也可以替换成Zookeeper锁,也是同样的机制。
  在小型项目中,使用:定时任务框架(QuartzSpringSchedule)和分布式锁(rediszookeeper)有不错的效果。
  但是呢?我们可以发现这种组合有两个问题:定时任务在分布式场景下有空跑的情况,而且任务也无法做到分片;要想手工触发任务,必须添加额外的代码才能完成。3ElasticJobLite框架
  ElasticJobLite定位为轻量级无中心化解决方案,使用jar的形式提供分布式任务的协调服务。
  应用内部定义任务类,实现SimpleJob接口,编写自己任务的实际业务流程即可。publicclassMyElasticJobimplementsSimpleJob{Overridepublicvoidexecute(ShardingContextcontext){switch(context。getShardingItem()){case0:dosomethingbyshardingitem0break;case1:dosomethingbyshardingitem1break;case2:dosomethingbyshardingitem2break;casen:。。。}}}
  举例:应用A有五个任务需要执行,分别是A,B,C,D,E。任务E需要分成四个子任务,应用部署在两台机器上。
  应用A在启动后,5个任务通过Zookeeper协调后被分配到两台机器上,通过QuartzScheduler分开执行不同的任务。
  ElasticJob从本质上来讲,底层任务调度还是通过Quartz,相比Redis分布式锁或者Quartz分布式部署,它的优势在于可以依赖Zookeeper这个大杀器,将任务通过负载均衡算法分配给应用内的QuartzScheduler容器。
  从使用者的角度来讲,是非常简单易用的。但从架构来看,调度器和执行器依然在同一个应用方JVM内,而且容器在启动后,依然需要做负载均衡。应用假如频繁的重启,不断的去选主,对分片做负载均衡,这些都是相对比较重的操作。
  ElasticJob的控制台通过读取注册中心数据展现作业状态,更新注册中心数据修改全局任务配置。从一个任务调度平台的角度来看,控制台功能还是偏孱弱的。4中心化流派
  中心化的原理是:把调度和任务执行,隔离成两个部分:调度中心和执行器。调度中心模块只需要负责任务调度属性,触发调度命令。执行器接收调度命令,去执行具体的业务逻辑,而且两者都可以进行分布式扩容。4。1MQ模式
  先谈谈我在艺龙促销团队接触的第一种中心化架构。
  调度中心依赖Quartz集群模式,当任务调度时候,发送消息到RabbitMQ。业务应用收到任务消息后,消费任务信息。
  这种模型充分利用了MQ解耦的特性,调度中心发送任务,应用方作为执行器的角色,接收任务并执行。
  但这种设计强依赖消息队列,可扩展性和功能,系统负载都和消息队列有极大的关联。这种架构设计需要架构师对消息队列非常熟悉。4。2XXLJOB
  XXLJOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
  xxljob2。3。0架构图
  我们重点剖析下架构图:
  网络通讯serverworker模型
  调度中心和执行器两个模块之间通讯是serverworker模式。调度中心本身就是一个SpringBoot工程,启动会监听8080端口。
  执行器启动后,会启动内置服务(EmbedServer)监听9994端口。这样双方都可以给对方发送命令。
  那调度中心如何知道执行器的地址信息呢?上图中,执行器会定时发送注册命令,这样调度中心就可以获取在线的执行器列表。
  通过执行器列表,就可以根据任务配置的路由策略选择节点执行任务。常见的路由策略有如下三种:随机节点执行:选择集群中一个可用的执行节点执行调度任务。适用场景:离线订单结算。
  广播执行:在集群中所有的执行节点分发调度任务并执行。适用场景:批量更新应用本地缓存。分片执行:按照用户自定义分片逻辑进行拆分,分发到集群中不同节点并行执行,提升资源利用效率。适用场景:海量日志统计。
  调度器
  调度器是任务调度系统里面非常核心的组件。XXLJOB的早期版本是依赖Quartz。
  但在v2。1。0版本中完全去掉了Quartz的依赖,原来需要创建的Quartz表也替换成了自研的表。
  核心的调度类是:JobTriggerPoolHelper。调用start方法后,会启动两个线程:scheduleThread和ringThread。
  首先scheduleThread会定时从数据库加载需要调度的任务,这里从本质上还是基于数据库行锁保证同时只有一个调度中心节点触发任务调度。ConnectionconnXxlJobAdminConfig。getAdminConfig()。getDataSource()。getConnection();connAutoCommitconn。getAutoCommit();conn。setAutoCommit(false);preparedStatementconn。prepareStatement(selectfromxxljoblockwherelocknameschedulelockforupdate);preparedStatement。execute();触发任务调度(伪代码)for(XxlJobInfojobInfo:scheduleList){省略代码}事务提交conn。commit();
  调度线程会根据任务的下次触发时间,采取不同的动作:
  已过期的任务需要立刻执行的,直接放入线程池中触发执行,五秒内需要执行的任务放到ringData对象里。
  ringThread启动后,定时从ringData对象里获取需要执行的任务列表,放入到线程池中触发执行。
  5自研在巨人的肩膀上
  2018年,我有一段自研任务调度系统的经历。
  背景是:兼容技术团队自研的RPC框架,技术团队不需要修改代码,RPC注解方法可以托管在任务调度系统中,直接当做一个任务来执行。
  自研过程中,研读了XXLJOB源码,同时从阿里云分布式任务调度SchedulerX吸取了很多营养。
  SchedulerX1。0架构图Schedulerxconsole是任务调度的控制台,用于创建、管理定时任务。负责数据的创建、修改和查询。在产品内部与schedulerxserver交互。Schedulerxserver是任务调度的服务端,是Scheduler的核心组件。负责客户端任务的调度触发以及任务执行状态的监测。Schedulerxclient是任务调度的客户端。每个接入客户端的应用进程就是一个的Worker。Worker负责与Schedulerxserver建立通信,让schedulerxserver发现客户端的机器。并向schedulerxserver注册当前应用所在的分组,这样schedulerxserver才能向客户端定时触发任务。
  我们模仿了SchedulerX的模块,架构设计如下图:
  我选择了RocketMQ源码的通讯模块remoting作为自研调度系统的通讯框架。基于如下两点:我对业界大名鼎鼎的Dubbo不熟悉,而remoting我已经做了多个轮子,我相信自己可以搞定;在阅读SchedulerX1。0client源码中,发现SchedulerX的通讯框架和RocketMQRemoting很多地方都很类似。它的源码里有现成的工程实现,完全就是一个宝藏。
  我将RocketMQremoting模块去掉名字服务代码,做了一定程度的定制。
  在RocketMQ的remoting里,服务端采用Processor模式。
  调度中心需要注册两个处理器:回调结果处理器CallBackProcessor和心跳处理器HeartBeatProcessor。执行器需要注册触发任务处理器TriggerTaskProcessor。publicvoidregisterProcessor(intrequestCode,NettyRequestProcessorprocessor,ExecutorServiceexecutor);
  处理器的接口:publicinterfaceNettyRequestProcessor{RemotingCommandprocessRequest(ChannelHandlerContextctx,RemotingCommandrequest)throwsException;booleanrejectRequest();}
  对于通讯框架来讲,我并不需要关注通讯细节,只需要实现处理器接口即可。
  以触发任务处理器TriggerTaskProcessor举例:
  搞定网络通讯后,调度器如何设计?最终我还是选择了Quartz集群模式。主要是基于以下几点原因:调度量不大的情况下,Quartz集群模式足够稳定,而且可以兼容原来的XXLJOB任务;使用时间轮的话,本身没有足够的实践经验,担心出问题。另外,如何让任务通过不同的调度服务(scheduleserver)触发,需要有一个协调器。于是想到Zookeeper。但这样的话,又引入了新的组件。研发周期不能太长,想快点出成果。
  自研版的调度服务花费一个半月上线了。系统运行非常稳定,研发团队接入也很顺畅。调度量也不大,四个月总共接近4000万到5000万之间的调度量。
  坦率的讲,自研版的瓶颈,我的脑海里经常能看到。数据量大,我可以搞定分库分表,但Quartz集群基于行级锁的模式,注定上限不会太高。
  为了解除心中的困惑,我写一个轮子DEMO看看可否work:去掉外置的注册中心,调度服务(scheduleserver)管理会话;引入zookeeper,通过zk协调调度服务。但是HA机制很粗糙,相当于一个任务调度服务运行,另一个服务standby;Quartz替换成时间轮(参考Dubbo里的时间轮源码)。
  这个Demo版本在开发环境可以运行,但有很多细节需要优化,仅仅是个玩具,并没有机会运行到生产环境。
  最近读阿里云的一篇文章《如何通过任务调度实现百万规则报警》,SchedulerX2。0高可用架构见下图:
  文章提到:
  每个应用都会做三备份,通过zk抢锁,一主两备,如果某台Server挂了,会进行failover,由其他Server接管调度任务。
  这次自研任务调度系统从架构来讲,并不复杂,实现了XXLJOB的核心功能,也兼容了技术团队的RPC框架,但并没有实现工作流以及mapreduce分片。
  SchedulerX在升级到2。0之后基于全新的Akka架构,这种架构号称实现高性能工作流引擎,实现进程间通信,减少网络通讯代码。
  在我调研的开源任务调度系统中,PowerJob也是基于Akka架构,同时也实现了工作流和MapReduce执行模式。
  我对PowerJob非常感兴趣,也会在学习实践后输出相关文章,敬请期待。6技术选型
  首先我们将任务调度开源产品和商业产品SchedulerX放在一起,生成一张对照表:
  Quartz和ElasticJob从本质上还是属于框架的层面。
  中心化产品从架构上来讲更加清晰,调度层面更灵活,可以支持更复杂的调度(mapreduce动态分片,工作流)。
  XXLJOB从产品层面已经做到极简,开箱即用,调度模式可以满足大部分研发团队的需求。简单易用能打,所以非常受大家欢迎。
  其实每个技术团队的技术储备不尽相同,面对的场景也不一样,所以技术选型并不能一概而论。
  不管是使用哪种技术,在编写任务业务代码时,还是需要注意两点:幂等。当任务被重复执行的时候,或者分布式锁失效的时候,程序依然可以输出正确的结果;任务不跑了,千万别惊慌。查看调度日志,JVM层面使用Jstack命令查看堆栈,网络通讯要添加超时时间,一般能解决大部分问题。7写到最后
  2015年其实是非常有趣的一年。ElasticJob和XXLJOB这两种不同流派的任务调度项目都开源了。
  在XXLJOB源码里,至今还保留着许雪里老师在开源中国的一条动态截图:
  刚写的任务调度框架,Web动态管理任务,实时生效,热乎的。没有意外的话,明天中午推送到git。osc上去。哈哈,下楼炒个面加个荷包蛋庆祝下。
  看到这个截图,内心深处竟然会有一种共情,嘴角不自禁的上扬。
  我又想起:2016年,ElasticJob的作者张亮老师开源了shardingjdbc。我在github上创建了一个私有项目,参考shardingjdbc的源码,自己实现分库分表的功能。第一个类名叫:ShardingDataSource,时间定格在2016329。
  我不知道如何定义有创造力的软件工程师,但我相信:一个有好奇心,努力学习,乐于分享,愿意去帮助别人的工程师,运气肯定不会太差。

荣耀赵明晒Magic5系列实拍照,网友呼唤发布会加一环节!荣耀Magic5系列的发布已经临近,昨天荣耀官方放出了倒计时三天的海报,海报中的主角依然是以等边三角形排列的后置摄像头,暗示荣耀Magic5系列有很强的拍照能力。此前荣耀……苹果watchOS7。6RC准正式版发布ECG功能登陆30个感谢IT之家网友榆吢的线索投递!IT之家7月14日消息今日凌晨,除iOS14。7与iPadOS14。7RC版外,苹果还面向开发者发布了watchOS7。6的RC(Rele……睡前两步法,让孩子远离近视,不花钱还超实用千万别忽视孩子的睡前护眼,孩子的睡前大量用眼,带着视疲劳入睡,会加快近视的增长速度。今天分享睡前两步法,缓解孩子的视疲劳,远离近视,不花钱还超实用。第一步眼部彻底放……比尔183盖茨像苹果这类企业应该受到政府严格监管IT之家8月23日消息据Appleinsider报道,微软创始人和前首席执行官比尔盖茨在一次采访中表示,苹果等大型科技公司应该受到政府的严格监管,这是大公司自然应该面对的一种挑……1979年来最长!南极臭氧层空洞再创新纪录,人类努力白费了?南极洲上空的臭氧层存在空洞,这已经是一个持续多年的问题,2021年也并不例外。根据美国宇航局(NASA)的消息,南极臭氧空洞于10月7日达到其最大面积,范围为1979年以来的第……2021年2月全球热门移动应用下载量排行榜抖音及TikTokIT之家3月10日消息SensorTower商店情报数据显示,2021年2月抖音及其海外版TikTok以5600万下载量,位列全球移动应用(非游戏)下载榜冠军。其中,抖音的下载……37996199元,苹果iPadmini6正式发布有史以来最IT之家9月15日消息说完iPad9,苹果现在拿出了万众期待的新一代iPadmini,也就是第六代iPadmini,宣称是有史以来最大的升级,引入了类似Air的全面屏设计,采用……iOS限免App精选趣味相机Epica2Pro重口味怪兽相机IT之家7月17日消息今天小编给IT之家小伙伴带来的iOS限免App是《Epica2Pro重口味怪兽相机》,这是一款趣味相机App。AppStore《Epica2Pro重……野菜赛人参,但野菜和毒草你分辨清楚吗科幻网4月13日讯(王子钰)野菜是指可以作蔬菜或用来充饥的野生植物,我国野菜的种类丰富,已达1000多种,分布的常见野菜有200种以上。每到春天这个时候,总有很多人喜欢挖点野菜……iOS限免App精选便签小组件记得(16510)IT之家7月12日消息今天小编给IT之家小伙伴带来的iOS限免App是《记得便签小组件》,这是一款可以在手机桌面添加便签小组件的工具。AppStore《记得》这款应……DigiTimes台积电2nm订单尘埃落下,三星5年内代工苹IT之家8月26日消息据媒体DigiTimes今日报道,台积电昨日确定2nm基地定址,3nm将在2022年下半年量产,且已与苹果确认进一步合作,对其下个制程节点规格与进度进行合……韩媒苹果决定从2022年开始为iPad使用OLED面板IT之家12月16日消息众所周知,AppleWatch和iPhone已经采用了OLED屏幕面板。韩国媒体电子日报称,苹果向三星和LG下单,请求将OLED面板应用于iPad系列产……
电动牙刷适合几岁孩子用?博主揭秘危害隐患作为专业口腔博主的林安在整理粉丝私信的时候发现,大家都想要给自家宝宝、小孩子、小朋友选购儿童电动牙刷,却不知道该怎么选。因对儿童电动牙刷不了解,跟风购买网红产品很容易会造成伤牙……辜卢密观察风投资金下降矿工收入减少加密经济飓风来袭?从市场数据来看,短期内,加密下跌的趋势和影响仍在持续。据区块链分析公司Glassnode最新数据显示,BTC钱包增长和活跃实体均出现停滞。尤其是在5月份加密市场遭到重创之……今年莫高窟所有游客均需提前预约2月28日,敦煌研究院发布《2022年莫高窟旅游开放公告》,公告显示,莫高窟开放旺季时间为4月1日至11月30日,淡季时间为12月1日至次年3月31日。开放期间,莫高窟将在全面……谢霆锋要为心上人做道菜不是王菲也不是张柏芝居然是经纪人霍汶希谢霆锋最爱的人竟不是张柏芝,也不是王菲。那究竟是谁呢?在一次节目中,谢霆锋称今天要给我最爱的人做一道菜。可这个人既不是王菲也不是张柏芝。谢霆锋在16岁时就顶着星二代的光环……正式确定!林书豪正式被北京首钢放弃续约,或就此彻底告别CBA北京首钢在首轮季后赛中被吉林队横扫后,很多媒体和北京球迷就展开了关于球队如何重建的大讨论。不过据知名篮球记者宋翔透露,北京首钢想要重建并没有那么容易,主要就是因为很多球员的合同……9月8日11家公司发布重大利好消息,1公司8月份销售同比增长一)上市公司重大利好消息海泰新光:自今年7月开始,12款新品4K荧光腹腔镜开始发货,按照美国客户的市场需求,7月少量出货、8月开始逐渐加大发货数量,预计下半年的内窥镜发货总量比……贤内助!乔治娜带大儿子看C罗比赛!这对母子相差16岁,五官神头条创作挑战赛贤内助!乔治娜带大儿子看C罗比赛!这对母子相差16岁,五官神似北京时间2023年1月24日星期二消息。C罗去哪里,哪里就是焦点。即便是在亚洲足球,在沙……最新春节放假期间工作安排通告【范文一】春节放假期间工作安排通告亲爱的:您好!春节将至,全体员工给您拜个早年,提前祝您春节愉快!根据全国假日办春节放假的相关规定,并结合公司实际……关于爱的花语鲜花常常是人们用来送人的,而最多的则是送给恋人,以表达爱意。今天品学网小编就来告诉你关于爱的花语,欢迎阅读。桔梗花的花语:真诚不变的爱传说,桔梗花开代表幸福再度降临。当幸……爱心捐款倡议书样本亲爱的老师、同学们:大家好!今天,当我们坐在宽敞明亮的教室里安静地学习,自在地生活的时候,当我们用着时尚的手机,吃着美味的零食,享受着优越的学习、生活环境的时候,在……读书活动总结汇总10篇总结是在某一特定时间段对学习和工作生活或其完成情况,包括取得的成绩、存在的问题及得到的经验和教训加以回顾和分析的书面材料,它在我们的学习、工作中起到呈上启下的作用,因此好好准备……2021入党积极分子培训心得新党章中明确提出了我们党是中国工人的先锋队,同时是中国人民和中华民族的先锋队,是中国特色社会主义事业的领导核心下面是品学网带来的20xx入党积极分子培训心得,仅供参考。20xx……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网