メインコンテンツへスキップ
検索

CACは、VOSメッセージキューの問題を調べるように頻繁に尋ねられています。ここでは、私があなたと共有したいいくつかの解決策や推奨事項とともに、興味深いものをいくつか紹介します。

問題1: 最近、ある顧客から問題が発生しました。依頼元がメッセージキューにメッセージを追加できず、エラーコード e$max_file_exceeded を受信しました。不思議なことに、list_messages コマンドを実行してみると、キューは空っぽになっていました。

キューを調べてみると、このキューに使用されているディスクブロックの数が、非エクステントファイルの最大ファイルサイズに近づいていることがわかりました。

名前: %s1#d01>AppData>queue.MQ

ファイル組織:メッセージキューファイル
最後に使用されたのは 11-08-16 14:45:13 EDT
最終更新日時:11-08-16 14:45:13 EDT 11-08-16 14:45:13 EDT
最後に保存されたのは 10-06-14 21:34:18 EDT
作成された時間。 10-06-09 11:03:15 EDT
トランザクションファイル: はい
保護されたログ: なし
安全スイッチ:なし
監査:なし
動的エクステント: なし
エクステントサイズ: 1
最後のメッセージ 51689380
ブロックを使用しています。 520201

なぜ、このキューは満席でもあり、空席でもあったのでしょうか?

過去のある時点で、メッセージをキューから排出する役割を担うサーバがオフラインになっていました。これは、非常に大きなメッセージのバックログをもたらしました。これらのメッセージは最終的にサーバによって処理され、キューから削除されました。メッセージがキューから削除されると、キューの _record_index インデックスにキーが追加され、 キーの値は削除されたメッセージのバイト数を示します。 新しいメッセージがメッセージキューに追加されると、ファイルシステムは、以前に削除されたメッセージの中から、新しいメッセージと同じサイズのものを見つけようとします。もし、そのようなメッセージがない場合、新しいメッセージは、キューの最後にあるバージンスペースに書き込まれます。

この場合、キューには新しいメッセージを格納するのに十分なバージンスペースがなく、適切なサイズの既存の削除されたメッセージが存在しませんでした。

この話の教訓は、任意の与えられたキュー内のユニークなメッセージの長さの数を制限することが良い考えであるということです。各メッセージがそれが必要とする正確なバイト数を使用するのではなく、 いくつかの標準的なサイズに値を丸めます。このテクニックを使用することで、新しいメッセージが以前に削除されたメッセージからのスペースを再利用することができる可能性が高くなります。

問題2: 最近、メッセージキューのパフォーマンスに関する別の状況が発生しました。ある顧客は、400,000以上のメッセージが入ったメッセージキューを空にするのに膨大な時間がかかっていると言っていました。

彼らは最近、サーバープロセスがメッセージキューのメッセージをタイムリーに処理できないという問題を抱えていました。幸いなことに、データが失われることがなかったように、リクエスターは実行され続けていました。サーバーの問題が解決したときには、バックログされたリクエストに追いつき、最近のトランザクションの処理を開始できるようになるまでに何時間もかかっていました。顧客は、なぜこのようなことが起こったのか、また、今後の状況でどのようにしてこれを防ぐか、あるいはスピードアップするかを尋ねていました。

メッセージ・キューでメッセージが削除されると、システムが保持する _record_index にキーが追加されます。削除されるメッセージが以前に削除されたメッセージと同じ長さである場合、未使用のデータ位置は、重複値のリストの最後に、そのメッセージサイズを含むキー上の重複エントリとして保存されます。したがって、削除されたメッセージが何十万もあり、すべて同じサイズである場合(または削除されたメッセージの長さのセットが小さい場合)、重複キーのリストは非常に長くなり、1つのメッセージを削除する時間は直線的に増加します。

逆に、メッセージがキューに追加され、メッセージ長のための _record_index キーが存在する場合、削除された最新のレコードによって占有された空間が、新しいメッセージのデータを格納するために再利用されます。その後、この値は、メッセージ長を含むキー値から削除されなければなりません。このようにして、メッセージを追加する時間は直線的に増加していきます。

この話の教訓は、システムがメッセージキューの中で維持しているデータはメモリを持っているということです; キューは以前のすべてのメッセージの位置とサイズを記憶しています。この情報は、キューが空になった後でも持続します。メッセージキューが巨大なサイズ (数万から数十万のディスクブロック) になるのを避けるようにしてください。そうしないと、キューにメッセージを追加したり削除したりするためのコストが、 時間の経過とともに大きくなってしまうことに気づくでしょう。

どちらも解決策は同じです。

解決策A: メッセージキューを開いている間に、メッセージキューを切り詰めることができます。ルーチン s$truncate_queue を使用してこれを達成することができます。しかし、満たされなければならない4つの条件があります。

1: メッセージキューを開いているリクエスタがいないこと

2: メッセージキューからすべてのメッセージを削除しなければなりません。

3: このルーチンはサーバから呼び出されなければなりません。

4: キューはトランザクションファイルであることができません。

最初の3つの条件が満たされない場合、s$truncate_queueはe$no_truncate_queueを返します。最後の条件が満たされない場合、s$truncate_queueはe$invalid_io_operationを返します。

解決策 B: アプリケーションの設計で複数のサーバを持つことができる場合、既存のメッセージキューの名前を定期的に変更し、正しい名前の新しいメッセージキューを作成し、新しいサーバのセットを起動し、要求者をバウンスさせることができます。サーバが起動すると、新しい、しかし空のメッセージキューで処理を開始します。リクエスト元が起動すると、新しい空のメッセージキューにリクエストを追加します。元のサーバのセットは、キューが空になるまでリクエストのバックログを処理して、 稼働し続けることができます。そして、古いサーバのセットを停止して、古いメッセージキューを削除することができます。

さらに、問題1の解決策は、エクステントベースのメッセージキューを使用することかもしれません。これは、最大ファイルサイズがエクステントサイズの一倍大きくなるので、 キューに追加のメッセージを配置することを可能にするでしょう。しかしながら、エクステントメッセージキューを使用することで、メッセージキューがある時点で大量のメッセージを含んでいる場合や、その時には、パフォーマンスは通常よりもさらに悪くなるでしょう。

前述したように、任意のキュー内のユニークなメッセージ長の数を制限することは、新しいメッセージが以前に削除されたメッセージによって解放された空間を再利用できる確率を向上させることになります。これは、この投稿で述べた両方の問題を解決するのに役立つでしょう。

メニューを閉じる

© 2024 Stratus Technologies.