Service Broker-会話の有効期間?


9

ビジネスケースを解決するために、Service Brokerを環境で動作させようとしています。メッセージのタイトルが適切かどうかはわかりませんが、私の質問は以下のとおりです。しかし、それは良い質問ではないかもしれません。そのため、私たちがやっていることと、それが正しい質問だと思う理由がここにあります。

会話を終了する前に、会話でいくつのメッセージを送信する必要がありますか?

結果テーブルを非同期で更新するために、Service Brokerを使用します。結果テーブルは平坦化され、高速です。ベーステーブルに、テーブルと主キーを含むメッセージを送信するトリガーがあります。3つのキューがあります。

  • 低レイテンシ-目標は処理に15秒です。特定のアイテムに関連して変更されるアイテムを処理します。
  • 一括キュー-目標は5分で処理されます。これは、何百(または何千)ものアイテムに影響を与える何かの変更を処理します。影響を受けたアイテムのリストを分割し、それらを遅延低遅延キューにフィードします
  • 遅延低遅延-目標は30分で処理されます。これはアイテムを処理しますが、バルクキューからのみです。

基本的に、クライアントの情報が更新された場合。これは多くの製品に影響を与えるため、処理を遅くするために一括キューに送信されます。ただし、製品が更新されると、それは低遅延キューに送信されます。

Remus Rusanuのブログhttp://rusanu.com/2007/04/25/reusing-conversations/と同様の会話を再利用しますが、主キーの係数に基づいて行う点が異なります。これには、主キーの重複排除を支援するという副次的な利点があります。

そのため、会話を再利用しており、ガイドラインの範囲内です。2つのスレッドで、125メッセージ/秒(数千のメッセージの人為的な低下)を焼き切ることができました。これは、生産(最大15メッセージ/秒)に追いつくのに十分です。

しかし、私たちが経験している問題は、一定の時間が経過すると、4時間または120Kメッセージの後に、sysdesendとキューテーブルでブロックと高い競合が発生し始めることです。ロックはLCK_M_Uであり、KEYロックです。hobtは、sysdesendに解決される場合もあれば、特定のキューテーブル(queue_)に解決される場合もあります。

24時間または30分の非アクティブ状態の後に会話を終了するプロセスが用意されているため、会話が循環するまでの時間を増やすことができます。

SQL 2016 Enterprise(13.0.4001.0)を使用しています

  1. トリガーの発火(低遅延または一括送信)
  2. 会話ハンドルを検索または作成します。
  3. メッセージを送る
  4. キューがアクティブ化された手順
  5. 結果テーブルを更新する

クリーンアッププロセスは10分ごとに実行され、アイドル状態の会話がないかどうかを確認します。連続して3回以上見つかった場合は、非アクティブとしてマークし、会話を終了します。

有益かもしれない追加の詳細があるかどうか私に知らせてください。Service Brokerの経験があまりないので、メッセージ/秒が低いか、高いか、無関心かはわかりません。

更新

そのため、本日もう一度試しましたが、同じ問題が発生しました。会話の有効期間を2時間に変更しましたが、影響はありませんでした。そこで、150トリックを実装しました。同じ問題がありました。

SEND CONVERSATIONでの大量の待機、sysdesendでの待機。誰か他のアイデアはありますか?

アップデート2

今日はさらに長い時間テストを実行し、17分のサンプル期間の1つで、4つの会話ハンドルで41Kのメッセージを処理しました。sysdesendとキューテーブルのロックが大きくなりすぎて停止する前にドリフトし始めたときを除いて、最後まで追いつくことができました。メッセージの処理には問題がないようですが、キューに入らない限り、メッセージを取り出して、少なくともその5倍の速度で処理できます。メッセージの追加に基づいて速度が制限されているようです。

後のテストで、メッセージの80%を占めるトリガーの1つを削除しました。このように負荷が大幅に軽減された場合でも、同じ待機が発生し始めました。

アップデート3

Remusからアドバイスをいただきありがとうございます(この件に関して優れたブログ記事を投稿していただき、ありがとうございました。この点に到達するために役立ちました)。

私たちは今日それをもう一度実行し、より良い結果を出しました(待機を見る前にさらに長くなり、それが私たちを不自由にする前にさらに長くなりました)。だから、詳細。

変更:*スレッドごとに維持される会話の数を1:1から2:1に増やしました。基本的に、4つのスレッドに対して8つの会話ハンドルがありました。

  • バルクキューを統合し(1つの受信メッセージが数百の送信メッセージを意味する可能性があるため)、少数の大きなメッセージに統合しました。

この試みに関するメモ:

  • ターゲットキューのアクティブ化手順を無効にします。ブロッキングに変更はなく(5分間待機)、メッセージはsys.transmission_queuesに送信されました。

  • sys.conversation_endpointsのモニタリング。この数は0から13,000まで急速に増加し、その後、1日を通してゆっくりと増加し、約5時間後には約25Kに達しました。ブロックは、16K +/-に達するまで発生しませんでした

  • 私はDACに入り、キューに対してDBREINDEXコマンドを実行しましたが、クエリから、ゴーストレコードが200を超えることはなく、クリーンアップが行われてカウントが0になりました。

  • テストを終了したとき、sysdesendとsysdercvのカウントは24,932でした。

  • 5時間で〜310Kのメッセージを処理しました。

物事がバラバラになるずっと前に行ったので、今度はそれを作ると本当に思った。明日は、メッセージを強制的に送信してみます。


1
we started seeing blocks and high contention on sysdesend and the queue table.->待機タイプとは何PAGELATCH_EX/SH and WRITELOGですか?150トリックを使用しましか?システムテーブルが競合ポイントである場合、150トリックは非常に役立ちます。
Kin Shah

@kin、質問を更新しましたが、ロックタイプはLCK_M_UまたはLCK_M_Xです。私は150トリックについて読みましたが、(tempdbリークの問題も解決されたため)2016年には必要ないことを期待していましたが、そのようなハッキングのようにも思われました。本番環境への移行時に別の試みを行い(残念ながら、これは本番環境のワークロードでのみ発生します)、最初に有効期間の短い会話を試みます。ここで結果を更新します。次はあなたが参照した150のトリックです。
Jonathan Fite、2017年

Twitterで@RemusRusanuに質問しました-彼はサービスブローカーに関するエキスパートです:-)
Kin Shah

これは私が以前に見たものではありません(長い実行時間後のSENDの低下)。1)sys.conversation_endpointsテスト中の行数を教えてください(定数または増加中、およびブロッキングが発生したときの大きさ)。2)ブロッキングが発生した場合、ターゲットキューを無効にする SENDブロッキングに違いが生じます(キューを無効にすると、SENDがsys.transmission_queueにルーティングされます)。および3)メッセージをローカルに(SSBエンドポイントをセットアップし、ルートを追加して)ワイヤーに強制的に送信すると、長期的には動作が変わります
Remus Rusanu

さらに考えてみましょう:4)ブロッキングが発生した場合、ターゲットでRECEIVEを停止すると違いがあります(アクティブ化されたプロシージャがある場合は無効化)、5)ターゲットキューにゴーストレコードがいくつあるか。ALTER QUEUE ... REBUILDブロッキングが開始されると、実行に違いが生じますか?
Remus Rusanu 2017年

回答:


3

自分の質問に答えるのは悪いことだと思いますが、興味のある人のためにこれを締めくくりました。私たちはようやく問題を解決することに成功しました、または少なくとも私たちの要件を満たすのに十分にそれを解決しました。コメントを提供してくれたすべての人に感謝したい。Remus RusanuとKinはとても役に立ちました。

データベースは非常にビジーで、RCSIモードです。45秒ごとに位置情報を更新するモバイルデバイスが複数(数千)あります。これらの更新により、複数のテーブルの情報が更新されます(揮発性情報を単一のテーブルに制限し、結果のために結合したため、設計が不十分です)。これらのテーブルは、エンドユーザーがベーステーブルに直接アクセスするのではなく、非同期にレポート情報を生成しようとしたものと同じです。

最初に、すべての更新/挿入ステートメント(ほとんどの場合は1行であるはずです)で変更されたレコードにカーソルを合わせてトリガーし、メッセージの各主キーをService Brokerに送信しました。Service Brokerの内部、特にバルクキューは、レポートの更新/挿入手順を実行する追加のカーソルでした(主キーごとに1つの実行)。

最終的に私たちを働かせたもの:

  • カーソルを削除し、より大きなメッセージを送信することにしました。それでも、テーブルごとのユーザートランザクションごとに1つのメッセージが送信されますが、複数の主キーを持つメッセージを送信するようになりました。

  • バルクプロセッサは、メッセージごとに複数のキーも送信します。これにより、メッセージを他のキューに適宜入れ替えるときに発生していたSEND CONVERSATIONSの数が減りました。

  • 最も揮発性の高いテーブル(モバイルデバイスのデータテーブル)では、トリガーが削除されました。upsertプロシージャを更新して適切な外部キーを含め、ユーザーに結果をフェッチするときにそのテーブルに結合するだけです。この表は、1日に処理しなければならないメッセージの80%を簡単に占めていました。

1日あたり約100万件のメッセージを処理し(モバイルテーブルを除く)、メッセージの大部分(99%以上)が目標内で処理されます。私たちはまだ時折外れ値を持っていますが、それが許容できると見なされるというまれな性質を考えると。

要因:

  • 前述の会話のクリーンアップ手順に、会話を実際に適切にクリーンアップせず、途中で終了してしまうバグが見つかりました。これにより、sysdesendカウントが数千を超えないようになりました(その大部分は150トリックを使用することで発生します)。

  • トリガー内のカーソルは、予想よりも多くのロックを保持しているように見えました(static、forward_onlyでも)。それらを削除することで、SEND CONVERSATIONで見られるロックがより本質的に一時的なものになったようです(少なくとも、見られる時間ははるかに短いです)。

  • 基本的に、2つのソリューション(Service Brokerソリューションバックエンド(運用負荷でのテスト用))と現在のソリューション(多くのテーブルにわたるひどいクエリ)を並べて実行していました。

副次的な利点として、これによりゴーストレコードのクリーンアップの問題が明らかになりました。ServiceBrokerテーブル(システムまたはキュー)にない間は、システムでかなり蔓延しており、症状は「明確な原因なし」と非常によく一致しています。私たちが時々経験する問題。調査は現在進行中です。調査に寄与しているテーブルを見つけようとしています。おそらく定期的にインデックスを再構築するだけです。

もう一度ありがとうございます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.