ビジネスケースを解決するために、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)を使用しています
- トリガーの発火(低遅延または一括送信)
- 会話ハンドルを検索または作成します。
- メッセージを送る
- キューがアクティブ化された手順
- 結果テーブルを更新する
クリーンアッププロセスは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のメッセージを処理しました。
物事がバラバラになるずっと前に行ったので、今度はそれを作ると本当に思った。明日は、メッセージを強制的に送信してみます。
sys.conversation_endpoints
テスト中の行数を教えてください(定数または増加中、およびブロッキングが発生したときの大きさ)。2)ブロッキングが発生した場合、ターゲットキューを無効にすると SENDブロッキングに違いが生じます(キューを無効にすると、SENDがsys.transmission_queueにルーティングされます)。および3)メッセージをローカルに(SSBエンドポイントをセットアップし、ルートを追加して)ワイヤーに強制的に送信すると、長期的には動作が変わります
ALTER QUEUE ... REBUILD
ブロッキングが開始されると、実行に違いが生じますか?
we started seeing blocks and high contention on sysdesend and the queue table.
->待機タイプとは何PAGELATCH_EX/SH and WRITELOG
ですか?150トリックを使用しましたか?システムテーブルが競合ポイントである場合、150トリックは非常に役立ちます。