溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

一次性集中處理大量數(shù)據(jù)的定時任務(wù),如何縮短執(zhí)行時間?

發(fā)布時間:2020-06-24 14:51:08 來源:網(wǎng)絡(luò) 閱讀:740 作者:架構(gòu)師追風(fēng) 欄目:編程語言

作者:58沈劍

問題抽象:
(1)用戶會員系統(tǒng);
(2)用戶會有分?jǐn)?shù)流水,每個月要做一次分?jǐn)?shù)統(tǒng)計,對不同分?jǐn)?shù)等級的會員做不同業(yè)務(wù)處理;
數(shù)據(jù)假設(shè):
一次性集中處理大量數(shù)據(jù)的定時任務(wù),如何縮短執(zhí)行時間?

(1)假設(shè)用戶在100w級別;
(2)假設(shè)用戶日均1條流水,也就是說日增流水?dāng)?shù)據(jù)量在100W級別,月新增流水在3kW級別,3個月流水?dāng)?shù)據(jù)量在億級別;
常見解決方案:
用一個定時任務(wù),每個月的第一天計算一次。

//(1)查詢出所有用戶
uids[] = select uid from t_user;
//(2)遍歷每個用戶
foreach $uid in uids[]{
         //(3)查詢用戶3個月內(nèi)分?jǐn)?shù)流水
        scores[]= select score from t_flow
                  where uid=$uid and time=[3個月內(nèi)];
         //(4)遍歷分?jǐn)?shù)流水
        foreach $score in scores[]{
                   //(5)計算總分?jǐn)?shù)
                  sum+= $score;
        }
         //(6)根據(jù)分?jǐn)?shù)做業(yè)務(wù)處理
        switch(sum)
        升級降級,發(fā)優(yōu)惠券,發(fā)獎勵;
}

一個月執(zhí)行一次的定時任務(wù),會存在什么問題?
計算量很大,處理的數(shù)據(jù)量很大,耗時很久,按照水友的說法,需要1-2天。
畫外音:外層循環(huán)100W級別用戶;內(nèi)層循環(huán)9kW級別流水;業(yè)務(wù)處理需要10幾次數(shù)據(jù)庫交互。
可不可以多線程并行處理?
可以,每個用戶的流水處理不耦合。
改為多線程并行處理,例如按照用戶拆分,會存在什么問題?
每個線程都要訪問數(shù)據(jù)庫做業(yè)務(wù)處理,數(shù)據(jù)庫有可能扛不住。
這類問題的優(yōu)化方向是:
(1)同一份數(shù)據(jù),減少重復(fù)計算次數(shù);
(2)分?jǐn)侰PU計算時間,盡量分散處理,而不是集中處理;
(3)減少單次計算數(shù)據(jù)量;
如何減少同一份數(shù)據(jù),重復(fù)計算次數(shù)?
一次性集中處理大量數(shù)據(jù)的定時任務(wù),如何縮短執(zhí)行時間?

如上圖,假設(shè)每一個方格是1個月的分?jǐn)?shù)流水?dāng)?shù)據(jù)(約3kW)。

3月底計算時,要查詢并計算1月,2月,3月三個月的9kW數(shù)據(jù);
4月底計算時,要查詢并計算2月,3月,4月三個月的9kW數(shù)據(jù);

會發(fā)現(xiàn),2月和3月的數(shù)據(jù)(粉色部分),被重復(fù)查詢和計算了多次。
畫外音:該業(yè)務(wù),每個月的數(shù)據(jù)會被計算3次。
新增月積分流水匯總表,每次只計算當(dāng)月增量:
flow_month_sum(month, uid, flow_sum)
(1)每到月底,只計算當(dāng)月分?jǐn)?shù),數(shù)據(jù)量減少到1/3,耗時也減少到1/3;
(2)同時,把前2個月流水加和,就能得到最近3個月總分?jǐn)?shù)(這個動作幾乎不花時間);
畫外音:該表的數(shù)量級和用戶表數(shù)據(jù)量一致,100w級別。
這樣一來,每條分?jǐn)?shù)流水只會被計算一次。
如何分?jǐn)侰PU計算時間,減少單次計算數(shù)據(jù)量呢?
業(yè)務(wù)需求是一個月重新計算一次分?jǐn)?shù),但一個月集中計算,數(shù)據(jù)量太大,耗時太久,可以將計算分?jǐn)偟矫刻臁?br/>一次性集中處理大量數(shù)據(jù)的定時任務(wù),如何縮短執(zhí)行時間?

如上圖,月積分流水匯總表,升級為,日積分流水匯總表。
把每月1次集中計算,分?jǐn)倿?0次分散計算,每次計算數(shù)據(jù)量減少到1/30,就只需要花幾十分鐘處理了。
甚至,每一個小時計算一次,每次計算數(shù)據(jù)量又能減少到1/24,每次就只需要花幾分鐘處理了。

雖然時間縮短了,但畢竟是定時任務(wù),能不能實時計算分?jǐn)?shù)流水呢?
每天只新增100w分?jǐn)?shù)流水,完全可以實時累加計算“日積分流水匯總”。
一次性集中處理大量數(shù)據(jù)的定時任務(wù),如何縮短執(zhí)行時間?

使用DTS(或者canal)增加一個分?jǐn)?shù)流水表的監(jiān)聽,當(dāng)用戶的分?jǐn)?shù)變化時,實時進(jìn)行日分?jǐn)?shù)流水累加,將1小時一次的定時任務(wù)計算,均勻分?jǐn)偟健懊繒r每刻”,每天新增100w流水,數(shù)據(jù)庫寫壓力每秒鐘10多次,完全扛得住。
畫外音:如果不能使用DTS/canal,可以使用MQ。

總結(jié),對于這類一次性集中處理大量數(shù)據(jù)的定時任務(wù),優(yōu)化思路是:
(1)同一份數(shù)據(jù),減少重復(fù)計算次數(shù);
(2)分?jǐn)侰PU計算時間,盡量分散處理(甚至可以實時),而不是集中處理;
(3)減少單次計算數(shù)據(jù)量;
希望大家有所啟示,思路比結(jié)論重要。

最后
歡迎大家一起交流,喜歡文章記得點個贊喲,感謝支持!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI