RocketMQ コミット ログ ストレージ プロトコルを再理解する

最近ふと思うのですが、多くのソフトウェアやハードウェアは、デザインではなく、その時々のシーンのニーズを解決するために根本的な理由があって設計されているのではないかと思います。一度それを理解すると、デザイナーと話しているように感じ、彼らの考え方を理解し、手法を学び、同じ画面上で考えることができるようになります。つまり、生きながら学ぶことができます。

問題思考

1. コンシューマ キュー オフセットは連続的ですか?なぜですか?

2. コミット ログ オフセットは連続していますか?なぜですか?

3. Java で書かれたファイルの場合、デフォルトはビッグエンディアンまたはリトルエンディアンです。

コミットログの実配布

皆さんが考えている間に、コミット ログがどのように配布されるかを思い出してみましょう。

Broker によって設定されたストレージ ルート ディレクトリで、Broker によって実際に生成されたコミット ログ ファイルを表示すると、次のようなデータ ファイルの分布を確認できます。

ブローカーの実データ ファイル ストレージの配布

実ストレージ ファイルが複数存在し、それぞれがファイル名として類似した数字の文字列を使用し、サイズが 1G であることがわかります。

ソース コードから、実際の抽象モデルは次のとおりであることがわかります。

コミットログストレージファイル配布の抽象化

上の図から、次のことがわかります。

コミット ログはファイルのクラスの名前であり、実際には多くのコミット ログ ファイルがあり、それぞれをコミット ログ ファイルと呼ぶことができます。図に示すように、コミットログファイルは合計 T 個あり、過去から現在までの作成時刻順に並んでいます。

各コミット ログ ファイルはメッセージを保存し、メッセージが書き込まれた順に保存し、常に作成時間が最も長いファイルを書き込み、同時に書き込みを行うスレッドは 1 つだけです。図の最初のファイル、1、2、3、4... はこのファイル内のメッセージの数を示しており、1234 番目のメッセージが最初のコミット ログ ファイルの最後のメッセージであり、1235 番目のメッセージであることがわかります。 2 番目のコミット ログの最初のメッセージ。

注 1: 各コミット ログ ファイル内のすべてのメッセージが占有する実際の記憶領域は 1G 以下です。なぜそうなるのか考えてみましょう。

説明 2: RocketMQ はコミット ログが書き込まれるたびにロックされます。コード スニペットについては、 https://github.com/apache/rocketmq/blob/7676cd9366a3297925deabcf27bb590e34648645/store/src/main/java/org/apache/rocketmq/store/を参照してください。 CommitLog.java#L676-L722

追加ロック

コミット ログ ファイルには、確立されたプロトコルに従って保存されている多くのメッセージがあることがわかります。具体的なプロトコルとは何ですか?また、それを知るにはどうすればよいですか?

コミットログストレージプロトコル

Commit Log の保存プロトコルについて ChatGPT に問い合わせたところ、このような回答があり、間違いではありますが、この回答の形式と記述は回答に非常に近いものです。

チャットGPT返信

ソース コードを見て詳しく説明しましょう: https://github.com/apache/rocketmq/blob/rocketmq-all-4.9.3/store/src/main/java/org/apache/rocketmq/store/ CommitLog.java #L1547-L1587

コミットログストレージプロトコル

整理してみるとこんな感じになりました。

私が理解しているコミットログ保存プロトコル

説明 1: 私が整理したメッセージ プロトコルの番号はコードと一致していません。コードは順序を示すだけであり、実際の物理ファイル内の格納プロトコルはさらに詳細になります。説明 2: 私が書いた「RocketMQ 分散メッセージ ミドルウェア: コア原則とベスト プラクティス」では、この図には本文の内容がありませんが、ここで追加されており、他のデータがより詳細に補足されています。説明が必要な問題がいくつかあります。

1. バイナリ プロトコルにはバイト オーダーがあり、多くの場合ビッグ エンディアンおよびリトル エンディアンと呼ばれます。ここでは大小については詳しく説明しません。興味のある学生は Google で検索するか、ChatGPT で質問してください。答えは私が言ったことよりも確実に優れています。

2. Java では、byte は 1 バイト、int は 4 バイト、short は 2 バイト、long は 8 バイトを占めます。

3. ホストのエンコードでは、単に IP:ポートを文字列として直接バイト配列に変換するのではなく、各数値をバイトとして順番にエンコードします。次のセクションの Golang コードで説明します。

4. 拡張情報のエンコードでは、不可視文字が区切りとして使用されるため、拡張フィールドの Key-Value にこれら 2 つの不可視文字を含めることはできません。どっちの2人ですか、探してみてください。

この契約を見た後、あなたの物理ファイルがこの契約に従って書かれていることをどのように証明できますか?

Golang を使用して RocketMQ コミット ログを紐解く

RocketMQ は Java で書かれています。上記のストレージ プロトコルに従って、コミット ログと顧客キューのロックを解除できるツールを Golang で書きました。コード アドレス: https://github.com/rmq-plus-plus/rocketmq -decoder

このツールは現在 2 つの機能をサポートしています。

1. コミット ログ サイトを指定し、コミット ログ内のメッセージを直接解析して出力します。

2. 消費場所を指定し、最初にコンシューマ キューを解析し、コミット ログ オフセットを取得します。次に、コミット ログ オフセットに従ってコミット ログを直接解析し、出力します。

Golang には RocketMQ に依存するコードはなく、純粋にプロトコルのデコードに依存します。

golangインポート

golang でコミット ログ オフセットを解析する例を次に示します。 Java では、このオフセットは 8 バイトを占める長いタイプです。

golang では、8 バイトのデータを読み取り、ビッグ エンディアン シーケンスに従って int64 にデコードすることで、通常のコミット ログ オフセットを取得できます。

Golang デモ参考までに、デモ結果を実行しました。

コンシューマーキューコミットログの読み取り

元の質問に答える

以下は私の個人的な意見ですので、ご参考までに。

1. コンシューマ キュー オフセットは連続的ですか?なぜですか?

継続的です。

コンシューマ キュー オフセットは、各キューのインデックス メッセージの添え字を指し、もちろん添え字は連続しています。消費者もこの連続性を利用して、空の消費サイトの送信を回避します。

各インデックス メッセージは同じスペース (20 バイト) を占有し、その構造は次のとおりです。

コンシューマキューインデックスのメッセージ構造

ここでの物理的な場所はコミット ログ オフセットです。

2. コミット ログ オフセットは連続していますか?なぜですか?

連続していません。

コミット ログ オフセットは、すべてのコミット ログ ファイル内の各メッセージのバイト オフセットを指します。各メッセージのサイズは不確実であるため、コミット ログ オフセット、つまりバイト オフセットは異なる必要があります。

そして、2 つのオフセットごとの差の絶対値が、前のメッセージのメッセージ バイトの合計長であることがわかります。

そして、上の図「コミットログ保存ファイルの分散抽象化」には誤解がありますが、実際にはそれぞれの小さな正方形のサイズが異なります。

3. Java で書かれたファイルの場合、デフォルトはビッグエンディアンまたはリトルエンディアンです。

ビッグエンディアン。ビッグエンディアンには実際にはバイト格納順序とネットワーク送信順序があり、Java のデフォルトのビッグエンディアン順序はネットワーク送信順序と同じままであり、エンコードとデコードに便利です。

ネットワーク トランスポート層の各セグメントのデータ メッセージの最初のバイトは、後続のデータの送信に使用されるプロトコルを表します。そのため、データ受信者がデータを受信すると、まずバイト順序に従ってプロトコルを解析し、次にデータをデコードします。プロトコルに従った後続のデータ 人間の考え方や問題解決の方法に沿ったバイトのシーケンス。

ディスカッションメモ解开: RocketMQ の一部のバージョンは異なる可能性があるため、この記事ではバージョン 4.9.3 で説明します。この方法、 5.0 または他のバージョン、および他のデータ ファイルのストレージ プロトコル形式を参照できます。

{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4587289/blog/8806657