Wir versuchen, Service Broker in unserer Umgebung zum Laufen zu bringen, um einen Business Case zu lösen. Ich weiß nicht, ob der Nachrichtentitel gut ist, aber meine Frage ist unten. Aber es ist vielleicht keine gute Frage, also ist es danach, was wir tun und warum ich denke, dass es die richtige Frage ist.
Wie viele Nachrichten sollten in einem Gespräch gesendet werden, bevor das Gespräch beendet wird?
Wir möchten Service Broker verwenden, um eine Ergebnistabelle asynchron zu aktualisieren. Die Ergebnistabelle ist abgeflacht und schnell. Wir haben Trigger für die Basistabellen, die eine Nachricht mit ihrer Tabelle und ihrem Primärschlüssel senden. Wir haben drei Warteschlangen:
- Geringe Latenz - Ziel ist die Verarbeitung von 15 Sekunden. Es behandelt Elemente, die sich in Bezug auf ein bestimmtes Element ändern.
- Massenwarteschlange - Ziel ist 5 Minuten zu verarbeiten. Es behandelt, wenn sich etwas ändert, das viele hundert (oder Tausende) Elemente betrifft. Es bricht die Liste der betroffenen Elemente auf und leitet sie an die Warteschlange für verzögerte niedrige Latenz weiter
- Aufgeschobene niedrige Latenz - Ziel ist die Verarbeitung von 30 Minuten. Dadurch werden Elemente verarbeitet, jedoch nur aus der Massenwarteschlange.
Grundsätzlich, wenn die Informationen eines Kunden aktualisiert werden; Dies betrifft viele Produkte, sodass sie zur langsameren Verarbeitung an die Massenwarteschlange gesendet werden. Wenn ein Produkt jedoch aktualisiert wird, wird es an die Warteschlange mit geringer Latenz gesendet.
Wir verwenden Konversationen ähnlich wie Remus Rusanus Blog http://rusanu.com/2007/04/25/reusing-conversations/ , mit der Ausnahme, dass wir dies basierend auf dem Modul des Primärschlüssels tun. Dies hat den Nebeneffekt, dass die Deduplizierung von Primärschlüsseln unterstützt wird.
Wir verwenden Gespräche also wieder und halten uns an unsere Richtlinien. Mit zwei Threads konnte ich 125 Nachrichten / Sekunde durchbrennen (künstlicher Tropfen von mehreren tausend Nachrichten), was mehr als in der Lage ist, mit der Produktion Schritt zu halten (ca. 15 Nachrichten / Sek.).
Das Problem, das wir haben, ist jedoch, dass nach einer Zeitspanne von ~ 4 Stunden oder 120.000 Nachrichten Blöcke und hohe Konflikte bei sysdesend und der Warteschlangentabelle auftreten. Die Sperren sind LCK_M_U und KEY-Sperren. Manchmal wird der Hobt in sysdesend und manchmal in die spezifische Warteschlangentabelle (queue_) aufgelöst.
Wir haben einen Prozess eingerichtet, der Gespräche bereits nach 24 Stunden oder 30 Minuten Inaktivität beendet, sodass wir die Zeit vor dem Überfahren von Gesprächen verlängern können.
Wir verwenden SQL 2016 Enterprise (13.0.4001.0)
- Auslöser auslösen (entweder an niedrige Latenz oder an Bulk senden)
- Nachschlagen oder Konversationshandle erstellen.
- Nachricht senden
- Warteschlangenaktivierte Prozedur
- Ergebnis-Tabelle aktualisieren
Der Bereinigungsprozess wird alle 10 Minuten ausgeführt, um festzustellen, ob Gespräche im Leerlauf stattfinden. Wenn sie mehr als dreimal hintereinander gefunden werden, werden sie als inaktiv markiert und die Konversationen beendet.
Bitte lassen Sie mich wissen, ob zusätzliche Details von Vorteil sind. Ich habe nicht viel Erfahrung mit Service Broker, daher weiß ich nicht, ob unsere Nachrichten / Sek. Niedrig, hoch oder gleichgültig sind.
AKTUALISIEREN
Also haben wir es heute noch einmal versucht und sind auf das gleiche Problem gestoßen. Wir haben die Gesprächslebensdauer auf 2 Stunden geändert, was keine Auswirkungen hatte. Also haben wir dann den 150-Trick implementiert; das hatte das gleiche Problem.
Tonnenweise Wartezeiten bei SEND CONVERSATION, die auf sysdesend warten. Hat jemand weitere Ideen?
UPDATE 2
Wir haben den Test heute länger durchgeführt und für einen der Beispielzeiträume von 17 Minuten 41.000 Nachrichten auf 4 Konversationshandles verarbeitet. Wir konnten mithalten, außer gegen Ende, als die Schlösser des Systems und der Warteschlangentabelle zu groß wurden und wir anfingen, hinterher zu driften, bevor wir sie stoppten. Wir scheinen kein Problem damit zu haben, Nachrichten zu verarbeiten. Ohne dass Dinge in die Warteschlange gelangen, können wir sie abziehen und mindestens fünfmal so schnell verarbeiten. Unsere Geschwindigkeit scheint aufgrund des Hinzufügens von Nachrichten begrenzt zu sein.
Bei einem späteren Test haben wir einen der Auslöser entfernt, auf die 80% der Nachrichten entfielen. Trotz dieser stark reduzierten Last sahen wir die gleichen Wartezeiten.
UPDATE 3
Vielen Dank, Remus, für Ihren Rat (und vielen Dank, dass Sie so hervorragende Blog-Artikel zu diesem Thema veröffentlicht haben, dass sie maßgeblich dazu beigetragen haben, diesen Punkt zu erreichen).
Wir haben es heute wieder laufen lassen und es besser gemacht (da wir länger gegangen sind, bevor wir die Wartezeiten gesehen haben und noch länger, bevor es uns verkrüppelt hat). Also die Details.
Wir haben Folgendes geändert: * Die Anzahl der gepflegten Konversationen pro Thread wurde von 1: 1 auf 2: 1 erhöht. Grundsätzlich hatten wir 8 Konversationshandles für 4 Threads.
- Konsolidierung der Massenwarteschlange (da eine eingehende Nachricht Hunderte von ausgehenden Nachrichten bedeuten kann) zur Konsolidierung in weniger, größeren Nachrichten.
Anmerkungen zu diesem Versuch:
Deaktivieren der Aktivierungsprozedur für die Zielwarteschlange. Keine Änderung beim Blockieren (wir haben 5 Minuten gewartet) und die Nachrichten wurden an sys.transmission_queues gesendet.
Überwachung von sys.conversation_endpoints. Diese Zahl stieg sehr schnell von 0 13K und stieg dann im Laufe des Tages langsamer an und endete nach ~ 5 Stunden bei 25K. Das Blockieren begann erst, als es 16K +/- erreichte.
Ich ging in den DAC und führte die DBREINDEX-Befehle für die Warteschlangen aus, obwohl nach einer Abfrage die Geisteraufzeichnungen vor der Bereinigung nie über 200 lagen und die Anzahl auf 0 sanken.
sysdesend und sysdercv hatten identische Zahlen von 24.932, als ich den Test beendete.
Wir haben ~ 310K Nachrichten in 5 Stunden verarbeitet.
Wir gingen so lange, bis die Dinge auseinander fielen, dass ich wirklich dachte, wir würden es diesmal schaffen. Morgen werden wir versuchen, die Nachrichten zu zwingen, durch den Draht zu gehen.
sys.conversation_endpoints
während des Tests vorhanden sind (konstant oder steigend und wie groß sie sind, wenn die Blockierung auftritt). 2) Wenn Blockieren auftritt, wird der Deaktivierung Zielwarteschlange einen Unterschied in SEND machen Blocking (Deaktivieren der Warteschlange sollte Route SEND sys.transmission_queue). und 3) Das Erzwingen, dass die Nachrichten auch lokal an die Leitung gesendet werden (SSB-Endpunkt einrichten, Routen hinzufügen), ändert das Verhalten auf lange Sicht
ALTER QUEUE ... REBUILD
einen Unterschied, sobald das Blockieren beginnt?
we started seeing blocks and high contention on sysdesend and the queue table.
-> Was ist der Wartetyp -PAGELATCH_EX/SH and WRITELOG
? Hast du den 150er Trick benutzt ? Wenn Systemtabellen Ihr Streitpunkt sind, ist der 150-Trick sehr nützlich.