一、背景
常用的定時任務一般有:JDK Timer、Spring Task、Quartz、xxl-job、Elastic-job。
JDK Timer:JDK自帶的定時任務,1.5之前不支持多線程,1.5之后加入了ScheduleThreadPool就是為了它,支持多線程;
Spring Task:Spring的定時任務,但是不支持集群;
Quartz:簡單、輕量級最常用的定時任務,支持集群;
xxl-job、Elastic-job:xxl-job是京東的一個架構師開發的定時任務,Elastic-job是當當網開源的一個定時任務,兩者都是基於Quartz開發的。
二、Quartz
1、Quartz主要有三個重要的組件:schedule、job、trigger,其中schedule是調度器,job就是我們要執行的任務,trigger是任務的觸發時間。其中job和trigger是1:N的關系,一個job可以綁定多個時間觸發。
2、trigger一共是四種:SimpleTrigger:固定時刻,固定時間間隔(毫秒) 、CalendarIntervalTrigger:時間單位、DailyTimeIntervalTrigger、CronTrigger:Cron表達式。
3、可以對job設置開啟時間,但是怎么排除一些時間呢,可以用Calendar,設置不同的時間,然后進行排除。Calendar包括:AnnualCalendar 、CronCalendar 、DailyCalendar 、HolidayCalendar、MonthlyCalendar 、WeeklyCalendar。
4、Quartz有監聽器,分別是jobListener、scheduleListener、triggerListener,可以針對三者進行監聽,當三者發生變動均可通過對應的監聽器獲取數據。
5、jobstore:持久化,默認持久化到內存,可修改成持久化到jdbc。
6、由於Quartz是一個容器,Spring也是一個容器,因此在Quartz中不能通過注入的方式直接拿到spring中的bean。可以通過自定義JobFactory生成Job,然后在生成Job的最后將Job放入spring容器中,然后將自定的jobFactory設置為job的factory就行了。
7、Quartz支持集群,在配置文件中配置集群相關的參數即可開啟集群模式,集群中只有一個節點能跑某一個任務,不會出現任務的重跑,當一個節點掛了,集群中的其他節點會有一個繼續跑定時任務,保證不漏跑。
原因:Quartz默認通過數據庫表的方式來設置鎖,數據庫中有一個表專門來存鎖字段,多個節點的調度器會執行一個sql來獲取鎖,獲取到鎖的節點執行定時任務。獲取鎖的sql是利用select for update來鎖的,執行完以后提交事務就釋放鎖,碰到異常會回滾事務也釋放鎖。也可用zk或者redis來實現,quartz默認用DB實現的。
三、Elastic-Job
1、Elastic-Job是當當開源的,其也是在Quartz的基礎上進行二次封裝使得更加的便捷好用。
2、 Elastic-Job目前分為兩個版本,一個是Elastic-Job-Lite,一個是Elastic-Job-Cloud,其實二者的api是一樣的就是部署方式不一樣而已,通過名字就能看出來Elastic-Job-Cloud是針對於微服務的部署方式的。Elastic-Job依賴zk作為注冊中心進行任務的分布式調度協調。
3、Elastic-Job的特性
3.1:使用zk作為注冊中心進行分布式調度協調以及節點的選舉;
3.3:錯過執行的作業重新執行(misfire);
3.4:支持並發(任務分片,同一個任務可以分成多片同時執行);
3.5:作業分片一致性,同一個時間點集群中同一個分片只有一個實例執行;
3.6:動態擴縮容:集群進行運行時會根據分片分配不同的任務,任務執行過程中當有新機器加入或者現有機器下線,那么elastic-job將保持現有作業不變的情況下繼續執行,在下次再次執行任務之前會重新進行任務的分片;
3.7:失效轉移:集群會在機器發生變化以后再次執行任務時重新分片,但是本次執行任務的過程中下線機器對應的任務不會繼續被執行。但是失效轉移可以利用空閑機器來執行孤兒任務,但是這會犧牲部分性能;
4.8、通過Listener支持作業周期內操作作業;
3.9、豐富的作業類型(Simple、DataFlow數據流、Script腳本)
3.10、有自己的運維平台,可監控任務的執行
4、Elastic的使用分為三步,整合到springboot中也是分為三步,分別是配置core、type、lite
core配置:配置zk地址、作業名稱、cron表達式、分片總數;
type配置:配置作業的類型,Simple、DataFlow、Script選擇一種作業的類型;
lite配置:配置lite部署或者cloud部署的一些參數配置,也可以配置分片的策略;
5、因為使用了zk作為注冊中心,故節點信息、數據的配置、分片的信息都能在zk的節點上看到;
6、運維平台的使用
源碼地址:https://github.com/elasticjob/elastic-job-lite,到該地址上找到elastic-job-lite-console打包,然后到本地進行解壓並執行bin/start.sh,訪問localhost:8899,賬號密碼是root/root,即可訪問控制台。
7、分片策略:例如有100個任務,剛才設置的是10個分片總數,那么其實分片項就是10,如果機器為5,那么每個機器分配的就是2個分片項。可以設置不用的分片策略,也可以自定義,具體哪些分片策略可以去官網看。
三、特殊情況處理
1、什么情況下會導致任務錯過觸發,兩個任務調度器都是怎么處理的?
沒有可用的線程、Trigger被暫停、系統重啟、禁止並發執行的任務在到達觸發時間時,上次執行還沒結束。
Quartz:每個trigger都有自己的MisFire策略,不同的策略通過不同的方法來執行,策略大致分為三種:忽略、立即跑一次、下次再跑。
Elastic-Job:錯過的作業下次重新執行。
2、如何避免任務錯過觸發?
合理設置線程池數量以及任務觸發間隔。
原文鏈接:https://blog.csdn.net/xiaoye319/article/details/106343126