作者:[email protected]
來源:http://www.expectfly.com/2017/08/15/分布式定時任務方案技術選型/
為什么我們需要定時任務
我們先思考下面幾個業務場景的解決方案:
- 支付系統每天凌晨1點跑批,進行一天清算,每月1號進行上個月清算
- 電商整點搶購,商品價格8點整開始優惠
- 12306購票系統,超過30分鐘沒有成功支付訂單的,進行回收處理
- 商品成功發貨后,需要向客戶發送短信提醒
類似的業務場景非常多,我們怎么解決?
很多業務場景需要我們某一特定的時刻去做某件任務,定時任務解決的就是這種業務場景,一般來說,系統可以使用訊息傳遞代替部分定時任務,兩者有很多相似之處,可以相互替換場景,
如,上面發貨成功發短信通知客戶的業務場景,我們可以在發貨成功后發送MQ訊息到佇列,然后去消費mq訊息,發送短信,
但在某些場景下不能互換:
a)時間驅動/事件驅動:內部系統一般可以通過時間來驅動,但涉及到外部系統,則只能使用時間驅動,如怕取外部網站價格,每小時爬一次
b)批量處理/逐條處理:批量處理堆積的資料更加高效,在不需要實時性的情況下比訊息中間件更有優勢,而且有的業務邏輯只能批量處理,如移動每個月結算我們的話費
c)實時性/非實時性:訊息中間件能夠做到實時處理資料,但是有些情況下并不需要實時,比如:vip升級
d)系統內部/系統解耦:定時任務調度一般是在系統內部,而訊息中間件可用于兩個系統間
有哪些定時任務的框架
單機
- timer:是一個定時器類,通過該類可以為指定的定時任務進行配置,TimerTask類是一個定時任務類,該類實作了Runnable介面,缺點例外未檢查會中止執行緒
- ScheduledExecutorService:相對延遲或者周期作為定時任務調度,缺點沒有絕對的日期或者時間
- spring定時框架:配置簡單功能較多,如果系統使用單機的話可以優先考慮spring定時器
分布
- Quartz:Java事實上的定時任務標準,但Quartz關注點在于定時任務而非資料,并無一套根據資料處理而定制化的流程,雖然Quartz可以基于資料庫實作作業的高可用,但缺少分布式并行調度的功能
- TBSchedule:阿里早期開源的分布式任務調度系統,代碼略陳舊,使用timer而非執行緒池執行任務調度,眾所周知,timer在處理例外狀況時是有缺陷的,而且TBSchedule作業型別較為單一,只能是獲取/處理資料一種模式,還有就是檔案缺失比較嚴重
- elastic-job:當當開發的彈性分布式任務調度系統,功能豐富強大,采用zookeeper實作分布式協調,實作任務高可用以及分片,目前是版本2.15,并且可以支持云開發
- Saturn:是唯品會自主研發的分布式的定時任務的調度平臺,基于當當的elastic-job 版本1開發,并且可以很好的部署到docker容器上,
- xxl-job: 是大眾點評員工徐雪里于2015年發布的分布式任務調度平臺,是一個輕量級分布式任務調度框架,其核心設計目標是開發迅速、學習簡單、輕量級、易擴展,
分布式任務調度系統對比
參與對比的可選系統方案: elastic——job (以下簡稱E-Job)與 xxx-job(以下簡稱X-Job)
專案背景及社區力量
X-Job : 大眾點評公司下員工許雪里、貢獻者 3人; github有2470star、1015fork | QQ討論群6個 | 有登記在使用的超過40家公司 | 檔案齊全
E-Job : 當當網開源,貢獻者17人; github有2524star、1015fork | QQ討論群1個、原始碼討論群1個 | 有登記在使用的超過50家公司 | 檔案齊全 | 有明確的發展計劃
支持集群部署
X-Job : 集群部署唯一要求為:保證每個集群節點配置(db和登陸賬號等)保持一致,調度中心通過db配置區分不同集群,
執行器支持集群部署,提升調度系統可用性,同時提升任務處理能力,集群部署唯一要求為:保證集群中每個執行器的配置項 “xxl.job.admin.addresses/調度中心地址” 保持一致,執行器根據該配置進行執行器自動注冊等操作,
E-Job : 重寫Quartz基于資料庫的分布式功能,改用Zookeeper實作注冊中心
作業注冊中心: 基于Zookeeper和其客戶端Curator實作的全域作業注冊控制中心,用于注冊,控制和協調分布式作業執行,
多節點部署時任務不能重復執行
X-Job : 使用Quartz基于資料庫的分布式功能
E-Job : 將任務拆分為n個任務項后,各個服務器分別執行各自分配到的任務項,一旦有新的服務器加入集群,或現有服務器下線,elastic-job將在保留本次任務執行不變的情況下,下次任務開始前觸發任務重分片,
日志可追溯
X-Job : 支持,有日志查詢界面
E-Job : 可通過事件訂閱的方式處理調度程序的重要事件,用于查詢、統計和監控,Elastic-Job目前提供了基于關系型資料庫兩種事件訂閱方式記錄事件,
監控告警
X-Job : 調度失敗時,將會觸發失敗報警,如發送報警郵件,
任務調度失敗時郵件通知的郵箱地址,支持配置多郵箱地址,配置多個郵箱地址時用逗號分隔
E-Job : 通過事件訂閱方式可自行實作
作業運行狀態監控、監聽作業服務器存活、監聽近期資料處理成功、資料流型別作業(可通過監聽近期資料處理成功數判斷作業流量是否正常,如果小于作業正常處理的閥值,可選擇報警,)、監聽近期資料處理失敗(可通過監聽近期資料處理失敗數判斷作業處理結果,如果大于0,可選擇報警,)
彈性擴容縮容
X-Job : 使用Quartz基于資料庫的分布式功能,服務器超出一定數量會給資料庫造成一定的壓力
E-Job : 通過zk實作各服務的注冊、控制及協調
支持并行調度
X-Job : 調度系統多執行緒(默認10個執行緒)觸發調度運行,確保調度精確執行,不被堵塞,
E-Job : 采用任務分片方式實作,將一個任務拆分為n個獨立的任務項,由分布式的服務器并行執行各自分配到的分片項,
高可用策略
X-Job : “調度中心”通過DB鎖保證集群分布式調度的一致性, 一次任務調度只會觸發一次執行;
E-Job : 調度器的高可用是通過運行幾個指向同一個ZooKeeper集群的Elastic-Job-Cloud-Scheduler實體來實作的,ZooKeeper用于在當前主Elastic-Job-Cloud-Scheduler實體失敗的情況下執行領導者選舉,通過至少兩個調度器實體來構成集群,集群中只有一個調度器實體提供服務,其他實體處于”待命”狀態,當該實體失敗時,集群會選舉剩余實體中的一個來繼續提供服務,
失敗處理策略
X-Job : 調度失敗時的處理策略,策略包括:失敗告警(默認)、失敗重試;
E-Job : 彈性擴容縮容在下次作業運行前重分片,但本次作業執行的程序中,下線的服務器所分配的作業將不會重新被分配,失效轉移功能可以在本次作業運行中用空閑服務器抓取孤兒作業分片執行,同樣失效轉移功能也會犧牲部分性能,
動態分片策略
X-Job : 分片廣播任務以執行器為維度進行分片,支持動態擴容執行器集群從而動態增加分片數量,協同進行業務處理;在進行大資料量業務操作時可顯著提升任務處理能力和速度,
執行器集群部署時,任務路由策略選擇”分片廣播”情況下,一次任務調度將會廣播觸發對應集群中所有執行器執行一次任務,同時傳遞分片引數;可根據分片引數開發分片任務;
E-Job : 支持多種分片策略,可自定義分片策略
默認包含三種分片策略: 基于平均分配演算法的分片策略、 作業名的哈希值奇偶數決定IP升降序演算法的分片策略、根據作業名的哈希值對Job實體串列進行輪轉的分片策略,支持自定義分片策略
elastic-job的分片是通過zookeeper來實作的,分片的分片由主節點分配,如下三種情況都會觸發主節點上的分片演算法執行:
a、新的Job實體加入集群
b、現有的Job實體下線(如果下線的是leader節點,那么先選舉然后觸發分片演算法的執行)
c、主節點選舉”
和quartz框架對比
- 呼叫API的的方式操作任務,不人性化;
- 需要持久化業務QuartzJobBean到底層資料表中,系統侵入性相當嚴重,
- 調度邏輯和QuartzJobBean耦合在同一個專案中,這將導致一個問題,在調度任務數量逐漸增多,同時調度任務邏輯逐漸加重的情況加,此時調度系統的性能將大大受限于業務;
- Quartz關注點在于定時任務而非資料,并無一套根據資料處理而定制化的流程,雖然Quartz可以基于資料庫實作作業的高可用,但缺少分布式并行調度的功能,
綜合對比

總結和結論
共同點:
E-Job和X-job都有廣泛的用戶基礎和完整的技術檔案,都能滿足定時任務的基本功能需求,
不同點:
X-Job 側重的業務實作的簡單和管理的方便,學習成本簡單,失敗策略和路由策略豐富,推薦使用在“用戶基數相對少,服務器數量在一定范圍內”的情景下使用,
E-Job 關注的是資料,增加了彈性擴容和資料分片的思路,以便于更大限度的利用分布式服務器的資源,但是學習成本相對高些,推薦在“資料量龐大,且部署服務器數量較多”時使用
附定時任務的其他方案
發貨后超過10天未識訓時系統自動確認識訓的多種實作方式:
每天定時半夜篩選第二天 可以自動確認識訓的訂單,然后第二天 每10分鐘 執行一次確認識訓 開銷不會太大吧 時間也相對精確
自動確認識訓這個狀態如果僅僅是讓客戶端看的話,等用戶下一次上線的時間,做一次運算就可以了,
延遲和定時訊息投遞
ActiveMQ提供了一種broker端訊息定時調度機制,適用于:1、不希望訊息馬上被broker投遞出去,而是想要訊息60秒以后發給消費者,2、想讓訊息沒隔一定時間投遞一次,一共投遞指定的次數
RabbitMQ可以針對Queue和Message設定 x-message-tt,來控制訊息的生存時間,如果超時,則訊息變為dead letter,利用DLX,當訊息在一個佇列中變成死信后,它能被重新publish到另一個Exchange,這時候訊息就可以重新被消費,
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2021最新版)
2.終于靠開源專案弄到 IntelliJ IDEA 激活碼了,真香!
3.阿里 Mock 工具正式開源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式發布,全新顛覆性版本!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/289129.html
標籤:Java
上一篇:有1、2、3、4個數字,能組成多少個互不相同 且無重復數字的三位數?都是多少?
下一篇:代碼重構終極指南!!
