ダボにおけるタイムホイールアルゴリズムの応用

ダボにおけるタイムホイールアルゴリズムの応用

[[346568]]

1 スケジュールされたタスク

Netty、Quartz、Kafka、Linux にはすべてスケジュールされたタスク機能があります。

JDK に付属する java.util.Timer と DelayedQueue は、単純なスケジュールされたタスクを実装できます。基礎となるレイヤーはヒープを使用し、アクセスの複雑さは O(nlog(n)) ですが、大規模なスケジュールされたタスクをサポートすることはできません。

タスク量が多く、パフォーマンス要件が高いシナリオでは、タイムホイールアルゴリズムを使用して、タスクアクセスとキャンセル操作の時間計算量を O(1) に削減します。

2 タイムホイールモデルとその応用

スケジュールされたタスクを効率的にバッチ管理するためのスケジューリング モデル。これは通常、時計に似たリング構造として実装され、多くのスロットに分割され、1 つのスロットは時間間隔を表し、各スロットは双方向リンク リストを使用してスケジュールされたタスクを格納します。

ポインタは定期的にジャンプし、スロットにジャンプすると、そのスロットのタイミング タスクが実行されます。

ハッシュタイミングホイール構造図

  • 障害回復
  • フロー制御
  • スケジューリングアルゴリズム
  • ネットワーク内のパケットのライフサイクルを制御する

タイマーの維持には費用がかかる

  • プロセッサはクロックごとに中断される
  • きめ細かいタイマーを使用する
  • 未完成のタイマーが多数あります

全体的な割り込みオーバーヘッドを削減するには、効率的なタイマー アルゴリズムが必要です。

単層タイムホイールの容量と精度には限界があります。特に高い精度が求められるシナリオ、特に長い時間範囲、またはスケジュールする必要のある大量のタスクがある場合、通常は、マルチレベル タイムホイールと、永続ストレージとタイムホイールを組み合わせたソリューションが使用されます。

モデルとパフォーマンスの指標

モデルのルール

クライアントからの呼び出し:

  • START_TIMER(間隔、リクエストID、有効期限アクション)
  • STOP_TIMER (リクエストID)

タイマーティック呼び出し:

  • ティックごとのブックキーピング
  • 有効期限処理

パフォーマンス指標

  • 空間

データ構造で使用されるメモリ

  • 遅れ

上記のルーチンの開始と終了にかかる時間

3 ダボのタイムホイール構造

Dubbo タイマーは、dubbo-common モジュールの org.apache.dubbo.common.timer パッケージに実装されています。次に、タイマーに関係するコア インターフェースと実装を分析します。

コアインターフェース

タイマータスク

Dubbo では、スケジュールされたすべてのタスクは TimerTask インターフェイスを実装する必要があります。定義されている run() メソッドは 1 つだけであり、入力パラメーターは Timeout インターフェイス オブジェクトです。

タイムアウト

Timeout オブジェクトは、スレッド プールによって返される Future オブジェクトとスレッド プールに送信されたタスク オブジェクトの関係と同様に、TimerTask オブジェクトと 1 対 1 で対応します。
Timeout オブジェクトを使用すると、スケジュールされたタスクのステータスを表示できるだけでなく、スケジュールされたタスクを操作することもできます (たとえば、関連するスケジュールされたタスクをキャンセルするなど)。

Timeout インターフェースのメソッド:

Timer インターフェイスはタイマーの基本的な動作を定義します。その中核となるのは newTimeout() です。つまり、スレッド プールにタスクを送信するのと同様に、時間制限付きタスク (TimerTask) を送信し、関連付けられた Timeout オブジェクトを返します。

ハッシュホイールタイムアウト

HashedWheelTimeout は、Timeout インターフェイスの唯一の実装であり、HashedWheelTimer の内部クラスです。 HashedWheelTimeout には 2 つの役割があります。

タイムホイール内の双方向リンクリストのノード、つまりHashedWheelTimer内のタイマータスクTimerTaskのコンテナ

タイマー タスク TimerTask が HashedWheelTimer に送信された後に返されるハンドルは、タイム ホイールの外部でタイマー タスクを表示および制御するために使用されます。

コア分野

前へ、次へ。二重リンク リストは、HashedWheelTimerBucket でタイムアウトを連鎖するために使用されます。これは WorkerThread でのみ機能するため、同期/揮発性は必要ありません。

task 、スケジュールされている実際のタスク

期限、スケジュールされたタスクが実行される時間。 HashedWheelTimeoutを作成するときは、計算式を指定します:currentTime(HashedWheelTimeoutが作成された時刻)+ delay(タスク遅延時間)- startTime(HashedWheelTimerの開始時刻)、ns

状態、スケジュールされたタスクの現在の状態

オプションのステータス:

STATE_UPDATER は、状態変更のアトミック性を実装するために使用されます。

residualRounds : 現在のタスクに残っているクロック サイクルの数。タイム ホイールが表すことができる時間の長さには制限があります。タスクの有効期限と現在の時刻の差が、タイム ホイールの 1 回転で表すことができる時間の長さを超えると、ループが発生し、残りのクロック サイクルを表すためにこのフィールドの値が必要になります。

コアAPI

キャンセルされました()

期限切れです()

州()
現在のHashedWheelTimeoutステータスを確認する

cancel()メソッド

expire()メソッド

取り除く()

ハッシュホイールバケット

時の車輪の中の隙間。
タイム ホイールのスロットは、実際には二重リンク リストをキャッシュして管理するためのコンテナーです。二重リンク リストの各ノードは、TimerTask タイミング タスクに関連付けられた HashedWheelTimeout オブジェクトです。

HashedWheelBucket は、双方向リンク リストの最初と最後のノード (先頭と末尾) を保持します。さらに、各 HashedWheelTimeout ノードは先行参照と後続参照を保持するため、リンク リスト全体を前方および後方にトラバースできます。

コアAPI

タイムアウトを追加します。

ポーリングタイムアウト()

取り除く()
指定された HashedWheelTimeout ノードを二重リンク リストから削除します。

タイムアウトをクリアする()
pollTimeout() メソッドは周期的に呼び出され、二重リンク リスト全体を処理して、タイムアウトまたはキャンセルされていないすべてのタスクを返します。

有効期限切れ()
二重リンク リスト内のすべての HashedWheelTimeout ノードを走査します。期限切れのスケジュールされたタスクを処理する場合、そのタスクは remove() メソッドによって取り出され、expire() メソッドが呼び出されて実行されます。キャンセルされたタスクの場合は、remove() メソッドによって取り出された後、直接破棄されます。期限切れになっていないタスクの場合は、remainingRounds フィールド (残りのクロック サイクル数) が 1 つ減ります。

ハッシュホイールタイマー

タイム ホイール アルゴリズムを通じてタイマーを実装する Timer インターフェイスの実装。

機能

現在のタイムホイール ポインターに従って対応する HashedWheelBucket スロットを選択し、リンク リストの先頭から反復処理して、各 HashedWheelTimeout スケジュール タスクを計算します。

  • 現在のクロックサイクルに属する場合は、取り出されて実行されます
  • グループに属していない場合は、残りのクロック サイクル数が 1 つ減少します。

コアドメイン

ワーカーステート
タイムホイールの現在の状態。AtomicIntegerFieldUpdater によってアトミックに変更される 3 つのオプション値。

開始時間
現在のタイム ホイールの開始時刻。このタイム ホイールに送信されたスケジュールされたタスクの期限フィールド値は、このタイムスタンプに基づいて計算されます。

車輪
タイムホイールの循環キュー。各要素はスロットです。タイムスロットの数がnと指定されている場合、nに最も近い2番目の累乗値が上方に取られます。

タイムアウト、キャンセルされたタイムアウト
HashedWheelTimer は、HashedWheelBucket の双方向リンク リストを処理する前に、これら 2 つのキューのデータを処理します。

タイムアウト キュー<br /> 外部送信タイムホイールでスケジュールされたタスクをバッファリングする

キャンセルされたタイムアウト キュー<br /> キャンセルされたスケジュールされたタスクを一時的に保存する

チェック
HashedWheelTimer$Workerにある、タイムホイールのポインター。ステップサイズが1の単調に増加するカウンター。

マスク
マスク、mask = wheel.length - 1、ticksとmaskを実行して対応するクロックスロットを見つけます

ティック期間
時間ポインターの各増分によって表される実際の時間はナノ秒単位です。

保留タイムアウト
現在のタイムラウンドに残っているスケジュールされたタスクの合計数。

ワーカースレッド
実際にタイミング タスクを実行するタイム ホイール内のスレッド。

ワーカー
スケジュールされたタスクを実際に実行するロジックは、この Runnable オブジェクトにカプセル化されます。

新しいタイムアウト()

スケジュールされたタスクを送信します。スケジュールされたタスクがタイムアウト キューに入る前に、start() メソッドが呼び出されてタイム ホイールが開始され、次の 2 つの重要な手順が完了します。

  1. タイムホイールのstartTimeフィールドを決定する
  2. workerThread スレッドを開始し、ワーカー タスクの実行を開始します。

次に、スケジュールされたタスクの期限が startTime に従って計算され、最後にスケジュールされたタスクは HashedWheelTimeout にカプセル化され、タイムアウト キューに追加されます。

4 タイムホイールポインターの1回転の実行フロー

HashedWheelTimer$Worker.run():

  1. タイムホイールのポインターが回転し、タイムホイールのサイクルが始まります
  2. ユーザーによって積極的にキャンセルされたスケジュールされたタスクをクリーンアップします。これらのスケジュールされたタスクがユーザーによってキャンセルされると、cancelledTimeouts キューに記録されます。ポインタが動くたびに、タイムホイールはキューをクリアします
  3. タイムアウトキューにキャッシュされたスケジュールされたタスクをタイムホイールの対応するスロットに転送します。
  4. 現在のポインタに従って対応するスロットを見つけ、スロットの双方向リンクリスト内のスケジュールされたタスクを処理します。
  5. タイムホイールの状態を確認します。タイムホイールが実行状態にある場合、上記の手順が周期的に実行され、タイミングタスクが継続的に実行されます。タイマーが停止状態の場合、次の手順を実行して、実行されていない時間指定タスクを取得し、それらを unprocessedTimeouts キューに追加します。タイマー内の各スロットを走査して clearTimeouts() メソッドを呼び出し、タイムアウト キューに追加されていないスロットに対して poll() を周期的に呼び出します。
  6. 最後に、ユーザーによってアクティブにキャンセルされた、cancelledTimeouts キュー内のスケジュールされたタスクをクリアします。

5 スケジュールされたタスクアプリケーション

これは定期的な操作に直接使用されるのではなく、タイム ホイールにスケジュールされた単一のタスクを送信するだけです。前のタスクが完了したら、newTimeout() メソッドを呼び出して現在のタスクを再度送信し、次のサイクルでタスクが実行されるようにします。タスク実行中に GC や I/O ブロッキングなどが発生し、タスクの遅延や詰まりが発生した場合でも、同じタスクが連続して送信されることはなく、タスクが蓄積されます。

Dubbo タイムホイールの用途は主に以下の分野です。

  1. 失敗の再試行。たとえば、プロバイダーがレジストリへの登録に失敗した場合や、コンシューマーがレジストリへのサブスクライブに失敗した場合などに再試行します。
  2. 定期的にスケジュールされたタスク(ハートビート要求を定期的に送信する、要求のタイムアウトを処理する、ネットワーク接続が切断された後に再接続するなど)

参照する

https://zhuanlan.zhihu.com/p/32906730

<<:  ノーコード プラットフォーム トップ 8: 2020 年に見逃せない機械学習プラットフォーム

>>:  アリババが国際AIサミットを主催、医療AIとマルチメディアコンテンツ理解が話題に

ブログ    
ブログ    

推薦する

RPAとAIの違いを理解する

CIO は自動化と AI の導入を加速し、これらのテクノロジーが提供するスピードとコスト削減の利点を...

...

GenAI時代のサイバー軍拡競争を生き残る方法

GenAIの急速な出現はすでにサイバーセキュリティに大きな変化をもたらし、各国政府に対策を取らせてお...

非人道的だ!人工知能はソーシャルエンジニアリングの天敵である

人工知能 (AI) はまだ初期段階ですが、AI は急速に企業が自らを守るための重要な手段になりつつあ...

...

Spark を使用して行列分解推奨アルゴリズムを学習する

[[182792]]協調フィルタリング推奨アルゴリズムにおける行列分解の応用では、推奨アルゴリズムに...

自動運転車のためのモデルベースのエンドツーエンドの深層強化学習戦略

実際の運転シナリオでは、観察と相互作用を通じて、インテリジェント運転車は知識を蓄積し、予測できない状...

掃除機はいくらかかりますか?掃除ロボットの原理とハードウェア構成の詳細な説明

時代の発展とともに、掃除ロボットは多くの家庭にとって必需品となりました。掃除ロボットは、ベッドの下を...

...

コードを入力せずに機械学習を行うことはできますか?アマゾンウェブサービスが今回大きな動きを見せた

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

AIとビッグデータでカスタマージャーニーを変革する方法

企業は AI とビッグデータを活用して、顧客体験をより良いものに変革することができます。人々はこれを...

...

ディープラーニングに関する面接で絶対に聞きたい12の質問

導入これら 12 の質問は、現在の面接で最も人気のある質問です。これらは非常に基本的な質問ですが、面...

TCP輻輳制御アルゴリズムについての簡単な説明

最近、TCP/IP プロトコルの学習に時間を費やしました。主な理由は、TCP/IP に関する私の理解...

75歳のヒントン氏が再び警告:AIが人間を支配するかもしれない!

10月9日、ヒントン氏は「60 Minutes」のインタビューを受け、人工知能が人間を支配するかも...