タイミングタスク高効率トリガ


物事をうまく処理すれば、目的が達成できます.
開発中、私たちは時々時間を決めて解決しなければならない業務シーンに遭遇します.例えば、「30 s連続してリクエストパケット(例えばログイン、メッセージ、keepaliveパッケージ)がない場合、サービス端末はこのユーザの状態をオフラインにする必要がある」という要求があります.
ポーリング処理
すべてのタスクをあるセットに追加し、タイミングポーリングスキャンを行い、条件が満たされたら関連処理を行います.
let map = new Map();
function doAction(uid) {
    map.set(uid, new Date().getTime());
}

setInterval(function(){
    for(let uid of map.keys()) {
        if(+new Date() - map.get(uid) > 30000) {
            map.delete(uid);
            console.log(`${uid}  30s      ,     !`);
        }
    }
}, 10000);
スキームの不足:
  • 効率が低い.すでに記録されていますが、まだスキャンされます.(結果集には現れないだけです.)大量の繰り返し計算があります.
  • 時効性の差.時間誤差はポーリングの間隔に依存する.間隔が小さいと、繰り返してスキャンする回数が高くなり、効率が悪くなります.
  • 定時に処理する
    一つのタスクごとにタイマーを起動し、タイマー時間に達したら関連処理を実行します.
    function doAction(uid) {
        map.set(uid, new Date().getTime());
        setTimeout(function() {
            console.log(`${uid}  30s      ,     !`);
        }, 30000);
    }
    スキームの不足:
  • タイミングが多すぎて、メモリの使用率が高すぎて、崩壊しやすいです.
  • ループ待ち行列処理
    データ構造:
  • リング状の列ListLoopは、例えば0-30を含むsloot*(本質は行列)を作成することができる.
  • 各リング上のタスクセットSlotは、各スリートがセットされている.
  • は、各TaskがSlotに落ちるMapセットに対応することを記録する.
  • 実行プロセス:第1ステップ:timerを起動し、1 sごとに、上記の環状列に1つの格を移動させ、0->1->2->3…->29->30->0…にCurrenntSlotIndexポインタがあり、検出されたばかりのslotを識別する.第二ステップ:あるユーザーのuidが要求されたカバンが届いた時、Map構造からこのuidがどのslotに保存されているかを検索します.ステップ3:存在する場合、このslot Set構造から、このuidを削除します.そうでなければ、ステップをスキップします.ステップ4:uidを新たなslot Indexポインタが指す前のslotに再加入する.このslotのために、timerによって30 s後にスキャンされ、Mapを更新し、このuid対応slotのindex値を再設定する.
    // new Array(31).fill(new Set())
    // No,     Set      
    
    let listLoop = new Array(31),
        map = new Map(),  //     uid slotIndex
        currentSlotIndex = 1; //       slot
    
    function doAction(uid) {
        //            uid,     ,    
        let slotIndex = map.get(uid);
        slotIndex && listLoop[slotIndex].delete(uid);
        //   uid          
        //   31,            ( ,30s       )
        //   map   uid   slotIndex
        slotIndex = currentSlotIndex - 1;
        listLoop[slotIndex] = listLoop[slotIndex] ? 
            listLoop[slotIndex].add(uid) : new Set().add(uid);
        map.set(uid, slotIndex);
    }
    
    //        slot,  slot   set     uid    
    //     slot   set     ,     uid  
    setInterval(function() {
        var slotSet = listLoop[currentSlotIndex];
        if(slotSet && slotSet.size > 0) {
            for(let uid of slotSet.values()) {
                //     uid map     
                map.delete(uid);
                console.log(`<${uid}>  30s      ,     !`);
            }
            //      
            slotSet.clear();
        }
        //     +1
        currentSlotIndex = (++currentSlotIndex) % 31;
    }, 1000);
    
    //   、  Map         。
    スキームの利点:
  • は注文を全部ポーリングする必要がなく、効率が高い
  • です.
  • 重複しないで実行して、一つの注文、任務は一回だけ実行します.
  • は、効率がよく、秒まで正確です.
    10 wタイミングタスクは、どのように高効率トリガタイムアウト、1分間で「遅延メッセージ」機能を実現しますか?
    一対三を挙げる
    上記の展示は、環状行列によって、多くの類似シーンを処理することができます.
  • あるタクシーアプリの注文が完了したら、ユーザーがずっと評価しないと48時間後に自動的に5スターと評価されます.
  • あるデータ製品のユーザーは設定を変更して、1時間後に有効になります.