Kafka には、遅延生成、遅延プル、遅延削除など、多数の遅延操作があります。 Kafka は、遅延機能を実装するために JDK に付属する Timer または DelayQueue を使用せず、代わりにタイム ホイールに基づいてタイマー (SystemTimer) をカスタマイズして遅延機能を実装します。 JDK の Timer および DelayQueue の挿入および削除操作の平均時間計算量は O(nlog(n)) であり、Kafka の高パフォーマンス要件を満たすことができません。ただし、挿入および削除操作の時間計算量は、タイムホイールに基づいて O(1) に削減できます。タイムホイールの応用は Kafka に特有のものではありません。他にも多くの応用シナリオがあります。タイムホイールは、Netty、Akka、Quartz、Zookeeper などのコンポーネントに含まれています。 下の図を参照してください。 Kafka の TimingWheel は、時間制限のあるタスクを格納するための循環キューです。基礎となるレイヤーは配列を使用して実装されます。配列内の各要素には、時間制限付きタスク リスト (TimerTaskList) を格納できます。 TimerTaskList は循環的な双方向リンク リストです。リンク リスト内の各項目は、実際のタイマー タスク TimerTask をカプセル化するタイマー タスク項目 (TimerTaskEntry) を表します。 タイム ホイールは複数のタイム グリッドで構成されており、各グリッドは現在のタイム ホイールの基本的な時間範囲 (ティック) を表します。タイミング ホイールの時間グリッドの数は固定されており、wheelSize で表現できます。次に、タイミング ホイール全体の全体的な時間範囲 (間隔) を、式 tickMs × wheelSize で計算できます。タイムホイールには、タイムホイールの現在の時刻を示すダイヤルポインター (currentTime) もあります。 currentTime は tickMs の整数倍です。 currentTime は、タイムホイール全体を期限切れ部分と期限切れでない部分に分割できます。現在 currentTime によって指されている時間グリッドも期限切れ部分に属しています。つまり、期限が切れたばかりであり、この時間グリッドに対応する TimerTaskList のすべてのタスクを処理する必要があることを意味します。 タイムホイールの tickMs が 1ms で wheelSize が 20 の場合、間隔は 20ms と計算されます。最初、ダイヤル ポインタ currentTime はタイム グリッド 0 を指しています。この時点で、タイマーが 2 ミリ秒のタスクが挿入され、タイム グリッド 2 の TimerTaskList に格納されます。時間が経過するにつれて、ポインタ currentTime は継続的に前進します。 2 ミリ秒後、タイム グリッド 2 に到達すると、タイム グリッド 2 に対応する TimeTaskList 内のタスクをそれに応じて期限切れにする必要があります。 この時点で 8 ミリ秒のタイマーを持つ別のタスクが挿入されると、そのタスクはタイム スロット 10 に格納され、さらに 8 ミリ秒後に currentTime はタイム スロット 10 を指すようになります。同時に 19 ミリ秒のタイマーを持つタスクが挿入された場合はどうなりますか?新しい TimerTaskEntry は元の TimerTaskList を再利用するため、すでに期限切れになっている時間スロット 1 に挿入されます。つまり、タイムホイール全体の全体的な範囲は変化しません。ポインター currentTime が進み続けると、現在のタイム ホイールが処理できる時間間隔も継続的に後方に移動し、全体的な時間範囲は currentTime と currentTime+interval の間になります。 350 ミリ秒にスケジュールされたタスクがある場合はどうすればよいでしょうか? wheelSize を直接拡張する必要がありますか? Kafka には、数万ミリ秒、あるいは数十万ミリ秒のスケジュールされたタスクが多数あります。 wheelSizeの拡張に制限はありません。スケジュールされたすべてのタスクの有効期限の上限を 100 万ミリ秒などに設定しても、wheelSize が 100 万ミリ秒のこのタイムホイールは大量のメモリ領域を占有するだけでなく、効率も低下します。 Kafka では、この目的のために階層型タイムホイールの概念を導入しています。タスクの有効期限が現在のタイム ホイールによって表される時間範囲を超えると、上位のタイム ホイールに追加しようとします。 上の図を参照して、前のケースを再利用し、*** レイヤーのタイムホイール tickMs=1ms、wheelSize=20、interval=20ms にします。第 2 層タイム ホイールの tickMs は、第 1 層タイム ホイールの間隔であり、20ms です。タイム ホイールの各レイヤーの wheelSize は 20 に固定されているため、タイム ホイールの 2 番目のレイヤーの全体的な時間範囲間隔は 400 ミリ秒になります。同様に、この 400 ミリ秒は第 3 層の tickMs のサイズでもあり、第 3 層のタイム ホイールの全体的な時間範囲は 8000 ミリ秒です。 前述の 350ms タイミング タスクの場合、第 1 層のタイム ホイールが条件を満たせないことは明らかなので、第 2 層のタイム ホイールにアップグレードし、最終的に第 2 層のタイム ホイールのタイム グリッド 17 に対応する TimerTaskList に挿入します。この時点でタイミングが 450 ミリ秒の別のタスクがある場合、明らかに第 2 レベルのタイム ホイールは条件を満たすことができないため、第 3 レベルのタイム ホイールにアップグレードされ、最終的に第 3 レベルのタイム ホイールのタイム グリッド 1 の TimerTaskList に挿入されます。有効期限が [400 ミリ秒、800 ミリ秒) の範囲にある複数のタスク (446 ミリ秒、455 ミリ秒、473 ミリ秒のスケジュールされたタスクなど) は、第 3 レベルのタイム ホイールのタイム グリッド 1 に配置されることに注意してください。タイム グリッド 1 に対応する TimerTaskList のタイムアウト期間は 400 ミリ秒です。 時間が経過し、TimerTaskList の有効期限が切れると、当初 450 ミリ秒でスケジュールされていたタスクの残り時間が 50 ミリ秒になり、このタスクの有効期限切れ操作は実行できなくなります。ここではタイム ホイールのダウングレード操作が行われ、残り時間が 50 ミリ秒のスケジュールされたタスクが階層型タイム ホイールに再送信されます。この時点で、第 1 レベルのタイム ホイールの全体的な時間範囲は十分ではありませんが、第 2 レベルのタイム範囲は十分であるため、タスクは有効期限が [40 ミリ秒、60 ミリ秒) の第 2 レベルのタイム ホイールの時間グリッドに配置されます。さらに 40 ミリ秒後にタスクが再び「検出」されますが、まだ 10 ミリ秒残っているため、有効期限切れ操作をすぐに実行することはできません。したがって、タイムホイールの別のダウングレードがあります。このタスクは、有効期限が [10ms、11ms) でトップレベルのタイムホイールのタイムグリッドに追加されます。さらに 10 ミリ秒後、このタスクは実際に期限切れになり、対応する期限切れ操作が最終的に実行されます。 デザインは生命から生まれます。私たちが普段使っている時計は、3層構造の時計ホイールです。タイムホイールの最初のレイヤーは tickMs=1ms、wheelSize=60、interval=1min で、秒数です。 2 番目のレイヤー tickMs=1min、wheelSize=60、interval=1hour (分)。 3 番目のレイヤーは tickMs=1hour、wheelSize は 12、interval は 12hours で、これは時計です。 Kafka では、最上位レベルのタイム ホイールのパラメーターは上記の場合と同じです: tickMs=1ms、wheelSize=20、interval=20ms。各レベルの wheelSize も 20 に固定されているため、各レベルの tickMs と interval もそれに応じて計算できます。 Kafka では、TimingWheel を実装する際にいくつかの細かい点があります。
これでタイムホイールの詳細説明は終了です。各コンポーネントにおけるタイムホイールの実装は同様です。読者は、この記事で説明されているシナリオ「時間が経つにつれて」または「時間が経つにつれて」に興味があるでしょうか。では、カフカでは時間はどのように進むのでしょうか。これは、JDK で scheduleAtFixedRate を使用してタイミング ホイールを 1 秒ごとに進めるのと似ていますか?明らかに、これは合理的ではなく、TimingWheel はその意味のほとんどを失っています。 Kafka のタイマーは、JDK の DelayQueue を使用してタイム ホイールを進めます。具体的なアプローチとしては、使用される各 TimerTaskList が DelayQueue に追加されます。 「使用された各 TimerTaskList」は、非センチネル ノードのスケジュールされたタスク項目 TimerTaskEntry を含む TimerTaskList を具体的に参照します。 DelayQueue は、対応する有効期限に従って TimerTaskList をソートし、有効期限が最も短い TimerTaskList を DelayQueue の先頭に配置します。 Kafka には、DelayQueue 内の期限切れのタスクのリストを取得するためのスレッドがあります。興味深いことに、このスレッドの名前は「ExpiredOperationReaper」であり、これは「期限切れの操作ハーベスター」と直訳でき、「SkimpyOffsetMap」に似ています。 「ハーベスター」スレッドは、DelayQueue 内のタイムアウトしたタスク リスト TimerTaskList を取得すると、TimerTaskList の有効期限に応じてタイマー ホイールの時間を進めるか、取得した TimerTaskList に対して対応する操作を実行できます。反対の TimerTaskEntry は、必要に応じて有効期限切れ操作を実行するか、必要に応じてタイマー ホイールをダウングレードします。 読者はこれを読んだ後、非常に混乱するかもしれません。記事の冒頭で明確に指摘したように、DelayQueue は、Kafka などの高パフォーマンス要件を伴うスケジュールされたタスクには適していません。ここで DelayQueue が導入されるのはなぜでしょうか?スケジュールされたタスク項目 TimerTaskEntry の挿入および削除操作の場合、TimingWheel の時間計算量は O(1) であり、パフォーマンスは DelayQueue よりもはるかに高いことに注意してください。 TimerTaskEntry を DelayQueue に直接挿入すると、パフォーマンスをサポートするのが明らかに難しくなります。特定のルールに従って複数の TimerTaskEntry を TimerTaskList グループに分割し、その TimerTaskList を DelayQueue に挿入したとしても、この TimerTaskList にもう 1 つの TimerTaskEntry を追加したい場合はどうすればよいでしょうか。 DelayQueue の場合、この種の操作は明らかにその能力を超えてしまいます。 この分析から、Kafka の TimingWheel は TimerTaskEntry 操作の挿入と削除に特に使用され、DelayQueue は時間を進めるタスクに特に責任があることがわかります。もう一度、DelayQueue 内の最初のタイムアウト タスク リストの有効期限が 200 ミリ秒で、2 番目のタイムアウト タスクの有効期限が 840 ミリ秒であると想像してください。ここで、DelayQueueの先頭を取得するには、O(1)の時間計算量のみが必要です。時間指定の進捗が毎秒採用される場合、最初のタイムアウト タスク リストが取得されたときに実行される 200 の進捗のうち 199 は「空の進捗」であり、2 番目のタイムアウト タスクが取得されたときに 639 の「空の進捗」を実行する必要があります。これにより、マシンのパフォーマンス リソースが無駄に浪費されます。ここで、DelayQueue は少量のスペースを時間と交換するのを補助するために使用され、それによって「正確な前進」を実現します。カフカにおけるタイマーは「人を知り、うまく活用する」ことだと言えます。 TimingWheel は、最も得意とするタスクの追加と削除の操作を実行するために使用され、DelayQueue は、最も得意とする時間の進行の作業を実行するために使用され、互いに補完し合います。 |
<<: 注意深い!クラウドコンピューティングの8つの隠れたコストに注意
>>: マルチクラウドは人気が高まり、ハイブリッドクラウドを上回り、企業の新たなお気に入りとなっている。
[51CTO.com からのオリジナル記事] 昨年の Yunqi Conference Beijin...
Hiformance はハイブリッド専用サーバー (hiformance VPS: $10/KVM/...
オンラインプロモーションにおけるロングテールキーワードの役割は極めて重要であると言えます。オンライン...
ご存知のとおり、buyvm の VPS サーバーの CPU 構成は比較的古く、一般的には L5638...
[[382060]]現在の企業 IT インフラストラクチャ技術の唯一の選択肢として、クラウド コンピ...
皆さんこんにちは。私は曹源葛です。前回のCool Grassrootsの記事では、ブランド構築につい...
ウェブマスターの分野では、ソフト記事は徐々に外部リンクを獲得し、サイトの重みを向上させるための最良の...
「百度優遇」がリリースされる前、淘宝網は百度による悪意あるクローリングを避けるために、当時話題を呼ん...
Budgetvm の SSD ハードディスク VPS は、1 ~ 2 か月間オンラインになっています...
ウェブサイトを設計する際、知らないうちに最適化の罠に陥ってしまうことが多々あり、それが後のウェブサイ...
5月26日夜、ピンドゥオドゥオは第1四半期の財務報告を発表した。これは黄正氏が会長を退任し、陳磊氏が...
最近では、オンライン収入で月に数万元、オンラインのアルバイトで月に4,000元や8,000元を稼ぐ本...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています一部のニッ...
11月に、spartanhostはシアトルデータセンターにハイエンドAMDシリーズVPS(AMD R...
今日、企業は競合他社よりも速く、高品質のソフトウェアを提供するという大きなプレッシャーにさらされてい...