日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
數(shù)十萬定時任務(wù),如何高效觸發(fā)定時和超時

項目產(chǎn)品中,大家都會有"定時任務(wù)"和"定時超時"的需求,初始階段,我們基本都是用少數(shù)的一些timer,即使是任務(wù)量越來越大的時候,我們就難免維護(hù)著大量的timer,或者進(jìn)行了大量低效的掃描。

創(chuàng)新互聯(lián)是一家專注于成都做網(wǎng)站、網(wǎng)站建設(shè)與策劃設(shè)計,新洲網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)十載,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:新洲等地區(qū)。新洲做網(wǎng)站價格咨詢:18982081108

定時任務(wù)使用場景:當(dāng)訂單一直處于未支付狀態(tài)時,如何及時的關(guān)閉訂單(已經(jīng)使用)

如何定期檢查處于退款狀態(tài)的訂單是否已經(jīng)退款成功(后期重構(gòu)使用)

設(shè)計方案:

  • 整個Redis當(dāng)做消息池,以KV形式存儲消息
  • 使用ZSET做優(yōu)先隊列,按照Score維持優(yōu)先級
  • 使用LIST結(jié)構(gòu),以先進(jìn)先出的方式消費(fèi)
  • ZSET和LIST存儲消息地址(對應(yīng)消息池的每個KEY)
  • 使用定時器維護(hù)路由
  • 根據(jù)TTL規(guī)則實現(xiàn)消息延遲

咱們公司現(xiàn)階段就是使用的這套方法:

1.新增一個job,會job_pool中插入一條數(shù)據(jù),記錄了業(yè)務(wù)方消費(fèi)方。也會在bucket插入一條記錄,記錄執(zhí)行的時間戳

2.搬運(yùn)線程會去bucket中查找哪些執(zhí)行時間戳的RunTimeMillis比現(xiàn)在的時間小,將這些記錄全部刪除;同時會解析出每個任務(wù)的Topic是什么,然后將這些任務(wù)PUSH到TOPIC對應(yīng)的列表queue中

3每個topic的list都會有一個監(jiān)聽線程去批量獲取list中的待消費(fèi)數(shù)據(jù),獲取到的數(shù)據(jù)全部扔給這個topic的消費(fèi)線程池

4.消費(fèi)線程池執(zhí)行會去job_pool查找數(shù)據(jù)結(jié)構(gòu),返回給回調(diào)結(jié)構(gòu),執(zhí)行回調(diào)方法。

圖片

待優(yōu)化的內(nèi)容:

  1. 目前只有一個Queue隊列存放消息,當(dāng)需要消費(fèi)的消息大量堆積后,會影響消息通知的時效。改進(jìn)的辦法是,開啟多個Queue,進(jìn)行消息路由,再開啟多個消費(fèi)線程進(jìn)行消費(fèi),提供吞吐量
  2. 消息沒有進(jìn)行持久化,存在風(fēng)險,后續(xù)會將消息持久化到MongoDB中

一般來說還有什么其他方法實現(xiàn)這類需求呢?

“輪詢掃描法”

1.用一個Map來記錄每一個uid最近一次請求時間last_packet_time

2.當(dāng)某個用戶uid有請求包來到,實時更新這個Map

3.啟動一個timer,當(dāng)Map中不為空時,輪詢掃描這個Map,看每個uid的last_packet_time是否超過30s,如果超過則進(jìn)行超時處理

“多timer觸發(fā)法”

1.用一個Map來記錄每一個uid最近一次請求時間last_packet_time

2.當(dāng)某個用戶uid有請求包來到,實時更新這個Map,并同時對這個uid請求包啟動一個timer,30s之后觸發(fā)

3.每個uid請求包對應(yīng)的timer觸發(fā)后,看Map中,查看這個uid的last_packet_time是否超過30s,如果超過則進(jìn)行超時處理

方案一:只啟動一個timer,但需要輪詢,效率較低

方案二:不需要輪詢,但每個請求包要啟動一個timer,比較耗資源

ZSet(有序集合)數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)

  1. 創(chuàng)建ZSet:首先,你需要創(chuàng)建一個ZSet數(shù)據(jù)結(jié)構(gòu),其中每個訂單將作為一個成員,其分?jǐn)?shù)將表示訂單的創(chuàng)建時間戳。你可以使用Redis等支持ZSet的數(shù)據(jù)庫來實現(xiàn)。
  2. 添加訂單:每當(dāng)用戶創(chuàng)建新訂單時,將訂單添加到ZSet中,其中成員是訂單ID,分?jǐn)?shù)是訂單的創(chuàng)建時間戳。
  3. 定時檢查訂單:定期(例如,每分鐘)執(zhí)行一個程序或定時任務(wù)來檢查ZSet中的訂單。你可以使用程序來查詢ZSet,找到創(chuàng)建時間超過一定時間閾值的訂單,表示它們長時間未支付。
  4. 取消訂單:對于那些長時間未支付的訂單,可以將其從ZSet中刪除,并執(zhí)行取消訂單的操作(例如,將訂單狀態(tài)設(shè)置為"已取消")。
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;
import java.util.Set;


public class OrderCancellationSystem {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost"); // 連接到本地Redis服務(wù)器


        // 模擬添加訂單
        addOrder(jedis, "Order1");
        addOrder(jedis, "Order2");


        // 定時任務(wù),每分鐘檢查訂單并自動取消
        while (true) {
            cancelLongUnpaidOrders(jedis);
            try {
                Thread.sleep(60000); // 等待一分鐘再次檢查
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public static void addOrder(Jedis jedis, String orderId) {
        long currentTime = System.currentTimeMillis();
        jedis.zadd("orders", currentTime, orderId);
    }


    public static void cancelOrder(String orderId) {
        // 執(zhí)行取消訂單操作,例如更新訂單狀態(tài)
        System.out.println("Cancelling order: " + orderId);
    }


    public static void cancelLongUnpaidOrders(Jedis jedis) {
        long expirationTime = System.currentTimeMillis() - 3600 * 1000; // 60分鐘前的時間戳
        Set longUnpaidOrders = jedis.zrangeByScoreWithScores("orders", "-inf", String.valueOf(expirationTime));


        for (Tuple order : longUnpaidOrders) {
            String orderId = order.getElement();
            cancelOrder(orderId);
            jedis.zrem("orders", orderId); // 從ZSet中刪除已取消的訂單
        }
    }
}


本文標(biāo)題:數(shù)十萬定時任務(wù),如何高效觸發(fā)定時和超時
網(wǎng)頁鏈接:http://www.5511xx.com/article/ccoscce.html