任務(wù)調(diào)度總結(jié)(二)

結(jié)合業(yè)務(wù)

相信以上說(shuō)了這么多,大家塵封已久的記憶已經(jīng)被徹底喚醒。那么,接下來(lái),我將要結(jié)合具體的業(yè)務(wù)場(chǎng)景,來(lái)說(shuō)說(shuō),我們?cè)谑褂眠^(guò)程中需要注意的點(diǎn)。我將分幾塊進(jìn)行說(shuō)明:

一、任務(wù)和場(chǎng)景

使用定時(shí)任務(wù)的場(chǎng)景總結(jié)如下:
1、補(bǔ)償機(jī)制:

當(dāng)我們?cè)谔幚順I(yè)務(wù)的時(shí)候,可能會(huì)存在處理無(wú)結(jié)果的情況。而此時(shí)不能用快速失敗來(lái)處理。

舉例:
支付在調(diào)用網(wǎng)關(guān)的時(shí)候,網(wǎng)關(guān)調(diào)用外部銀行渠道存在很多不可控的因素,如網(wǎng)絡(luò)超時(shí),或者銀行沒(méi)有返回明確結(jié)果的情況。這個(gè)時(shí)候,為了防止資損,我們采用了異步補(bǔ)償?shù)姆绞?,掉單查詢?/p>

image.png

這里要說(shuō)明下,一般這種情況是消息結(jié)合定時(shí)查詢來(lái)做的。行業(yè)內(nèi)通俗做法。

那么這里的查詢就是定時(shí)任務(wù)來(lái)做的。借助數(shù)據(jù)庫(kù),進(jìn)行查詢并更新的操作。

2、特殊業(yè)務(wù)要求

這里舉個(gè)很通俗的例子:對(duì)賬。
無(wú)論是第三方支付公司還是銀行,都存在清結(jié)算系統(tǒng),凌晨或者t+1都會(huì)進(jìn)行跑批,對(duì)賬。
那么這個(gè)對(duì)賬就是定時(shí)任務(wù)來(lái)做的。

所以,這種場(chǎng)景就是業(yè)務(wù)數(shù)據(jù)落地后,異步在某個(gè)時(shí)間點(diǎn)觸發(fā),進(jìn)行特殊的業(yè)務(wù)操作。那么觸發(fā)動(dòng)作就是定時(shí)任務(wù)的職責(zé)了。

總結(jié)下
在聯(lián)機(jī)操作沒(méi)有明確結(jié)果的情況下,或者失敗的情況下,需要重試或者補(bǔ)償,保證操作最終成功。那么定時(shí)任務(wù)就發(fā)揮作用了。
另外,某些特殊的業(yè)務(wù),如對(duì)賬等功能,就是異步t+1通過(guò)跑批來(lái)做的。這個(gè)異步跑批就是定時(shí)任務(wù)的職責(zé)。
最后,我們?cè)趯?xiě)一些中間件的時(shí)候,少不了的就是心跳機(jī)制,心跳機(jī)制也是通過(guò)定時(shí)任務(wù)來(lái)做的。通俗做法。

二、任務(wù)和鎖

上面,講了通用的場(chǎng)景操作。那么定時(shí)任務(wù)在處理的時(shí)候,需要注意些什么。

總結(jié)如下幾點(diǎn):
1、任務(wù)緯度:哪些機(jī)器跑這個(gè)任務(wù)。
2、任務(wù)緯度:任務(wù)失敗了怎么辦?
3、數(shù)據(jù)緯度:數(shù)據(jù)會(huì)被多個(gè)任務(wù)執(zhí)行么?
4、數(shù)據(jù)緯度:數(shù)據(jù)可以被多個(gè)任務(wù)一起處理么?

下面我就來(lái)一一解釋下:

老早的土鱉做法:

定時(shí)任務(wù)跟隨著應(yīng)用啟動(dòng)。如何確認(rèn)數(shù)據(jù)不被重復(fù)執(zhí)行呢?很簡(jiǎn)單,就是只在集群的一臺(tái)機(jī)器上啟動(dòng)定時(shí)任務(wù)。

這個(gè)時(shí)候,怎么做?

服務(wù)啟動(dòng)的時(shí)候jvm參數(shù) -Dxxxxx來(lái)注入啟動(dòng)參數(shù)。

這種做法的缺點(diǎn)顯而易見(jiàn):
服務(wù)的啟動(dòng)腳本變成了有狀態(tài),或者有差異了。無(wú)論對(duì)于發(fā)布,還是專業(yè)度而言,都很low。

我目前在的這家公司,目前負(fù)責(zé)的系統(tǒng),就曾經(jīng)因?yàn)檫@個(gè)腳本的問(wèn)題導(dǎo)致資損。

升級(jí)做法:
去除腳本的差異化。那么這個(gè)時(shí)候可以通過(guò)鎖機(jī)制來(lái)實(shí)現(xiàn)。下面我就來(lái)詳細(xì)的說(shuō)說(shuō)怎么做:
、每臺(tái)服務(wù)器在啟動(dòng)的時(shí)候,都會(huì)去搶占一把公共鎖。如果搶到,那么他就執(zhí)行定時(shí)任務(wù)。任務(wù)就是你的了。
這樣做的好處是,任務(wù)啟動(dòng)無(wú)狀態(tài),隨機(jī),隨時(shí)。
這樣做不好的地方是:依賴鎖機(jī)制。如果出現(xiàn)死鎖,或者第三方依賴異常,那么可能會(huì)影響任務(wù),最后影響業(yè)務(wù)的運(yùn)行。

當(dāng)然,有補(bǔ)救的方法,那就是繼續(xù)補(bǔ)償嘍。這個(gè)里面的補(bǔ)償,并非繼續(xù)再加一個(gè)定時(shí)任務(wù)。
而是,增加任務(wù)的批次和執(zhí)行結(jié)果,配以監(jiān)控和報(bào)警,再加上人工觸發(fā)的接口。是不是perfect了?回答是必須的。如果這種做法再出問(wèn)題。我揮刀自刎謝罪。哈哈。

所以,我們?cè)诙x定時(shí)任務(wù)的時(shí)候,建議做法如下:
1、建任務(wù)的批次表
2、建任務(wù)的執(zhí)行日志表
3、對(duì)任務(wù)的執(zhí)行者采用分布式鎖機(jī)制。
4、增加報(bào)警和監(jiān)控機(jī)制。
5、增加手工觸發(fā)入口,以備不時(shí)之需。

OK,這里補(bǔ)充下兩種鎖機(jī)制:
1、悲觀鎖
2、樂(lè)觀鎖

我們一般會(huì)采用悲觀鎖的方式。悲觀鎖,顧名思義,就是爭(zhēng)搶鎖的發(fā)起者,很悲觀。認(rèn)為所有人都會(huì)和他競(jìng)爭(zhēng)。所以搶到了立刻把鑰匙拿走。

通俗的做法是:用共享存儲(chǔ)來(lái)做鎖。mysql or zookeeper?

對(duì)于mysql來(lái)說(shuō),做悲觀鎖可能有點(diǎn)麻煩。因?yàn)閕nnerdb需要支持悲觀鎖,那么就要關(guān)閉數(shù)據(jù)庫(kù)層面的auto commit。且如果沒(méi)有指定具體的主鍵,將是表級(jí)鎖。so,我們慎用。所以,一般推薦用zookeeper來(lái)做?;蛘咦兿嗟脑跀?shù)據(jù)庫(kù)層面用樂(lè)觀鎖來(lái)實(shí)現(xiàn)悲觀鎖的方式。

、分布式任務(wù)調(diào)度系統(tǒng)
對(duì)比以上,任務(wù)只能由一臺(tái)執(zhí)行。數(shù)據(jù)處理的效率并沒(méi)有那么高。所以分布式任務(wù)調(diào)度系統(tǒng),很好的解決這個(gè)問(wèn)題。對(duì)數(shù)據(jù)進(jìn)行分片。將條件注入到sql中去。這里就不再贅述了。推薦大家看下tbscheduler和elastic-job。

好了,夜深人靜??偨Y(jié)到此。希望對(duì)大家對(duì)認(rèn)識(shí)和問(wèn)題的處理有所幫助。

最后,附上我的筆記和我的一些代碼示例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容