淺談分散式定時任務之quartz

zxhy發表於2019-05-05

前言

最近一段時間因公司專案需要進行分散式定時任務框架選型,由於資源(人力,時間)有限,所以重點考慮採用開源的一些解決方案,其中重點比較了3款框架:quartz,elastic-job,xxl-job等。由於elastic-job 和xxl-job 實際上也是基於quartz實現的。所以很有必要對quartz 有一定的瞭解。所以近期閱讀了大量quartz相關的一些文件和部落格,以及寫了一些demo進行驗證。本文主要是對近期工作的一個小結,簡要的介紹一下quartz 這個分散式定時任務排程框架。

目錄

  • 什麼是quartz?它有哪些特性?
  • quartz 核心概念和元素介紹
  • quartz 常用配置項介紹
  • quartz 叢集介紹

一.什麼是quartz?它有哪些特性?

quartz 是一個開源的分散式排程庫,它基於java實現。
> 它有著強大的排程功能,支援豐富多樣的排程方式,比如簡單排程,基於cron表示式的排程等等。
> 支援排程任務的多種持久化方式。比如支援記憶體儲存,資料庫儲存,Terracotta server 儲存。
> 支援分散式和叢集能力。
> 採用JDBCJobStore方式儲存時,針對事務的處理方式支援全域性事務(和業務服務共享同一個事務)和區域性事務(quarzt 單獨管理自己的事務)
> 基於plugin機制以及listener機制支援靈活的擴充套件。
複製程式碼

二. quartz 核心概念和元素介紹:

  • Job: 工作任務。它提供了一個介面,只有一個方法void execute(JobExecutionContext context),開發者實現該介面定義執行任務,JobExecutionContext類提供了排程上下文的各種資訊。Job執行時的資訊儲存在JobDataMap例項中.

  • JobDetail:工作任務例項.Quartz在每次執行Job時,都重新建立一個Job例項,所以它不直接接受一個Job的例項,相反它接收一個Job實現類,以便執行時通過newInstance()的反射機制例項化Job。因此需要通過一個類來描述Job的實現類及其它相關的靜態資訊,如Job名字、描述、關聯監聽器等資訊,JobDetail承擔了這一角色.

  • Trigger:觸發器,用來描述觸發Job執行的時間觸發規則。主要有SimpleTrigger和CronTrigger這兩個子類。當僅需觸發一次或者以固定時間間隔週期執行,SimpleTrigger是最適合的選擇;而CronTrigger則可以通過Cron表示式定義出各種複雜時間規則的排程方案:如每早晨9:00執行,週一、週三、週五下午5:00執行等.

  • Calendar:日曆,它表示一些特定時間點的集合.一個Trigger可以和多個Calendar關聯,以便排除或包含某些時間點。假設,我們安排每週星期一早上10:00執行任務,但是如果碰到法定的節日,任務則不執行,這時就需要在Trigger觸發機制的基礎上使用Calendar進行定點排除。

  • Scheduler:排程器,代表一個Quartz的獨立執行容器,Trigger和JobDetail可以註冊到Scheduler中,兩者在Scheduler中擁有各自的組及名稱,組及名稱是Scheduler查詢定位容器中某一物件的依據,Trigger的組及名稱必須唯一,JobDetail的組和名稱也必須唯一(但可以和Trigger的組和名稱相同,因為它們是不同型別的)。Scheduler定義了多個介面方法,允許外部通過組及名稱訪問和控制容器中Trigger和JobDetail。

      Scheduler可以將Trigger繫結到某一JobDetail中,這樣當Trigger觸發時,對應的Job就被執行。一個Job可以對應多個Trigger,但一個Trigger只能對應一個Job。
    複製程式碼

三. quarz 常用配置項介紹

quartz 預設的配置檔案是quartz.properties ,裡面有很多配置項,比如排程器(schedule)相關配置,事務的配置,監聽器,外掛的配置,rmi 相關配置,叢集相關配置等等。 詳細配置資訊可以參照官方文件:www.quartz-scheduler.org/documentati…

四. quratz 叢集介紹

quartz 叢集是依賴於資料庫機制實現的。部署多個節點的quartz 資料庫配置必須保持一致。quartz叢集是通過資料庫表來感知其他的應用的,各個節點之間並沒有直接的通訊。只有使用持久的JobStore才能實現Quartz叢集。

quartz 預設提供了11張資料庫表:

  • QRTZ_CALENDARS: 儲存Quartz的Calendar資訊

  • QRTZ_CRON_TRIGGERS:儲存CronTrigger,包括Cron表示式和時區資訊

  • QRTZ_FIRED_TRIGGERS:儲存與已觸發的Trigger相關的狀態資訊,以及相聯Job的執行資訊

  • QRTZ_PAUSED_TRIGGER_GRPS:儲存已暫停的Trigger組的資訊

  • QRTZ_SCHEDULER_STATE:儲存少量的有關Scheduler的狀態資訊,和別的Scheduler例項

  • QRTZ_LOCKS:儲存程式的悲觀鎖的資訊

  • QRTZ_JOB_DETAILS:儲存每一個已配置的Job的詳細資訊

  • QRTZ_SIMPLE_TRIGGERS:儲存簡單的Trigger,包括重複次數、間隔、以及已觸的次數

  • QRTZ_BLOG_TRIGGERS Trigger作為Blob型別儲存

  • QRTZ_TRIGGERS 儲存已配置的Trigger的資訊

  • QRTZ_SIMPROP_TRIGGERS:儲存簡單觸發器相關。

    要注意的是quartz叢集間的相互感知是通過資料庫表(QRTZ_SCHEDULER_STATE)實現的。對於水平叢集,存在著時間同步問題。節點用時間戳來通知其他例項它自己的最後檢入時間。假如節點的時鐘被設定為將來的時間,那麼執行中的Scheduler將再也意識不到那個結點已經宕掉了。另一方面,如果某個節點的時鐘被設定為過去的時間,也許另一節點就會認定那個節點已宕掉並試圖接過它的Job重執行。
    複製程式碼

小結

本文只是對quartz 分散式定時任務做了一個簡單的介紹。quartz 作為一個成熟的分散式定時任務框架,然而好像並沒有提供友好的運維管理介面,幸運的是很多的開源框架彌補了這個不足,比如elastic-job ,xxl-job等等,關於quartz 的更多內容,在後面不斷的實踐中再補充。

相關文章