Staramy się, aby Service Broker działał w naszym środowisku, aby rozwiązać przypadek biznesowy. Nie wiem, czy tytuł wiadomości jest dobry, ale moje pytanie jest poniżej. Ale może to nie być dobre pytanie, więc po tym jest to, co robimy i dlaczego uważam, że jest to właściwe pytanie.
Ile wiadomości należy wysłać w rozmowie przed jej zakończeniem?
Chcemy użyć Service Brokera, aby asynchronicznie zaktualizować tabelę wyników. Tabela wyników jest spłaszczona i szybka. Mamy wyzwalacze w tabelach podstawowych, które wysyłają komunikat z ich tabelą i kluczem podstawowym. Mamy trzy kolejki:
- Niskie opóźnienie - realizacja celu trwa 15 sekund. Obsługuje elementy, które zmieniają się w odniesieniu do określonego elementu.
- Kolejka masowa - realizacja celu zajmuje 5 minut. Zajmuje się, gdy coś się zmienia, co wpływa na setki (lub tysiące) przedmiotów. Rozbija listę elementów, których dotyczy problem, i podaje je do kolejki o opóźnionym niskim opóźnieniu
- Odroczone niskie opóźnienie - realizacja celu zajmuje 30 minut. Przetwarza elementy, ale tylko z kolejki zbiorczej.
Zasadniczo, jeśli informacje klienta są aktualizowane; wpływa to na wiele produktów, dlatego jest wysyłane do kolejki zbiorczej w celu spowolnienia przetwarzania. Jeśli jednak produkt zostanie zaktualizowany, zostanie wysłany do kolejki o niskim opóźnieniu.
Ponownie wykorzystujemy rozmowy podobne do bloga Remusa Rusanu http://rusanu.com/2007/04/25/reusing-conversations/ , z tym wyjątkiem, że robimy to w oparciu o moduł klucza podstawowego. Ma to dodatkową zaletę polegającą na pomocy w usuwaniu duplikacji kluczy głównych.
Dlatego ponownie wykorzystujemy rozmowy i jesteśmy w zgodzie z naszymi wytycznymi. Dzięki dwóm wątkom udało mi się wypalić 125 wiadomości na sekundę (sztuczny spadek kilku tysięcy wiadomości), co jest więcej niż w stanie nadążyć za produkcją (szacunkowo 15 wiadomości na sekundę).
Jednak problem, z jakim się spotykamy, polega na tym, że po pewnym czasie ~ 4 godzin lub 120 000 wiadomości zaczęliśmy widzieć bloki i dużą rywalizację o sysdesend i tabelę kolejek. Zamki są LCK_M_U i są zamkami KEY. Czasami hobt decyduje się na sysdesend, a innym razem na określoną tablicę kolejek (kolejka_).
Mamy wdrożony proces, który zakończy rozmowy już po 24 godzinach lub 30 minutach bezczynności, dzięki czemu moglibyśmy po prostu wydłużyć czas przed przejściem do rozmowy.
Używamy SQL 2016 Enterprise (13.0.4001.0)
- Wyzwalanie pożarów (wysyłanie do małych opóźnień lub luzem)
- Wyszukaj lub utwórz uchwyt konwersacji.
- Wyślij wiadomość
- Procedura aktywowana w kolejce
- Zaktualizuj tabelę wyników
Proces czyszczenia jest uruchamiany co 10 minut, aby sprawdzić, czy są jakieś bezczynne rozmowy. jeśli znajdzie je więcej niż trzy razy z rzędu, oznacza to jako nieaktywne i kończy rozmowy.
Daj mi znać, jeśli są jakieś dodatkowe szczegóły, które mogą być korzystne. Nie mam dużego doświadczenia z Service Brokerem, więc nie wiem, czy nasze wiadomości / s są niskie, wysokie czy obojętne.
AKTUALIZACJA
Więc spróbowaliśmy dzisiaj jeszcze raz i napotkaliśmy ten sam problem. Zmieniliśmy czas trwania rozmowy na 2 godziny i to nie miało żadnego efektu. Więc wdrożyliśmy lewę 150; który miał ten sam problem.
Mnóstwo oczekiwań na WYŚLIJ KONWERSACJĘ, czeka na sysdesend. Czy ktoś ma jakieś dalsze pomysły?
AKTUALIZACJA 2
Dzisiaj przeprowadziliśmy test dłużej i przez jeden z przykładowych okresów 17 minut przetworzyliśmy 41 000 wiadomości na 4 uchwytach konwersacji. Byliśmy w stanie nadążyć za wyjątkiem końca, kiedy blokady na sysdesend i tabela kolejek stały się zbyt duże i zaczęliśmy dryfować z tyłu, zanim go zatrzymaliśmy. Wydaje się, że nie mamy problemu z przetwarzaniem wiadomości, bez rzeczy wchodzących do kolejki możemy je ściągnąć i przetworzyć co najmniej 5 razy szybciej. Nasza prędkość wydaje się być ograniczona w oparciu o dodawanie wiadomości.
W późniejszym teście usunęliśmy jeden z wyzwalaczy, które stanowiły 80% wiadomości. Nawet przy tak znacznie zmniejszonym obciążeniu zaczęliśmy widzieć te same oczekiwania.
AKTUALIZACJA 3
Dziękuję, Remus za radę (i dziękuję za opublikowanie tak doskonałych artykułów na blogu na ten temat, które przyczyniły się do osiągnięcia tego celu).
Ponownie uruchomiliśmy go dzisiaj i zrobiliśmy lepiej (ponieważ poszliśmy dłużej, zanim zobaczyliśmy oczekiwania, a nawet dłużej, zanim nas kaleczył). A więc szczegóły.
Zmieniliśmy: * Zwiększono liczbę utrzymywanych rozmów w wątku z 1: 1 do 2: 1. Zasadniczo mieliśmy 8 uchwytów konwersacji dla 4 wątków.
- skonsolidował kolejkę zbiorczą (ponieważ jedna wiadomość przychodząca może oznaczać setki wiadomości wychodzących), aby skonsolidować ją w mniejszą, większą liczbę wiadomości.
Uwagi na temat tej próby:
wyłączenie procedury aktywacji kolejki docelowej. brak zmian w blokowaniu (czekaliśmy 5 minut) i wiadomości zostały wysłane do sys.transmission_queues.
monitorowanie sys.conversation_endpoints. Liczba ta wzrosła bardzo szybko od 0 13K, a następnie wolniej rosła w ciągu dnia, kończąc na około 25K po ~ 5 godzinach. Blokowanie nie zaczęło się pojawiać, dopóki nie osiągnęło 16K +/-
Poszedłem do DAC-a i uruchomiłem polecenia DBREINDEX dla kolejek, chociaż po zapytaniu rekordy duchów nigdy nie przekroczyły wartości około 200 przed nadejściem czyszczenia i spadły do zera.
sysdesend i sysdercv miały identyczną liczbę 24 932, kiedy zakończyłem test.
przetworzyliśmy ~ 310 000 wiadomości w ciągu 5 godzin.
Przeszliśmy tak długo, zanim wszystko się rozpadło, że naprawdę myślałem, że tym razem się uda. Jutro spróbujemy zmusić wiadomości do przejścia przez drut.
źródło
we started seeing blocks and high contention on sysdesend and the queue table.
-> Jaki jest typ oczekiwania -PAGELATCH_EX/SH and WRITELOG
? Czy wykorzystałeś już lewę 150 ? Jeśli twoje tabele systemowe są twoim punktem spornym, trik 150 będzie bardzo przydatny.sys.conversation_endpoints
podczas testu (stała lub rośnie i jak duża jest, gdy nastąpi blokowanie). 2) Gdy nastąpi blokowanie, powoduje wyłączenie kolejki docelowej robi różnicę w blokowaniu SEND (wyłączenie kolejki powinno kierować SEND do sys.transmission_queue). i 3) Zmuszenie wiadomości, aby przechodziły na drut, nawet lokalnie (skonfiguruj punkt końcowy SSB, dodaj trasy) zmienia zachowanie na dłuższą metęALTER QUEUE ... REBUILD
robi różnicę po rozpoczęciu blokowania?Odpowiedzi:
Wiem, że odpowiedź na twoje pytanie jest zła, ale chciałem to zamknąć dla wszystkich zainteresowanych. W końcu udało nam się rozwiązać problem lub przynajmniej rozwiązać go wystarczająco, aby spełnić nasze wymagania. Chcę podziękować wszystkim, którzy wnieśli komentarze; Remus Rusanu i Kin, ponieważ byli bardzo pomocni.
Nasza baza danych jest dość zajęta i znajduje się w trybie RCSI. Mamy wiele (tysiące) urządzeń mobilnych, które aktualizują informacje o swojej lokalizacji co 45 sekund. Dzięki tym aktualizacjom wiele tabel aktualizuje swoje informacje (kiepski projekt, ponieważ ograniczyłbym zmienne informacje do jednej tabeli, a następnie dołączyłem ją w celu uzyskania wyników). Te tabele są tymi samymi, które próbowaliśmy asynchronicznie wygenerować informacje raportowania, zamiast zmuszać użytkowników końcowych do bezpośredniego korzystania z tabel podstawowych.
Początkowo wyzwalacze robiły kursor nad zmodyfikowanymi rekordami w każdej instrukcji aktualizacji / wstawiania (w większości przypadków powinien to być jeden wiersz) i wysyłały każdy klucz podstawowy w komunikacie do brokera usług. Wewnątrz brokera usług, zwłaszcza kolejki zbiorczej, znajdowały się dalsze kursory, które wykonały procedurę upsert dla raportu (jedno wykonanie na klucz podstawowy).
Co w końcu sprawiło, że pracowaliśmy:
Usunęliśmy kursory i zdecydowaliśmy się na wysyłanie większych wiadomości. Wciąż jedna wiadomość na transakcję użytkownika na tabelę, ale teraz wysyłamy wiadomości z więcej niż jednym kluczem podstawowym.
Procesor masowy wysyła również wiele kluczy na wiadomość, co zmniejszyło liczbę WYSYŁANYCH KONWERSACJI, które tasowały wiadomości do innej kolejki, stosownie do przypadku.
Najbardziej niestabilna tabela (nasza tabela danych urządzeń mobilnych) miała usunięte wyzwalacze. Zaktualizowaliśmy procedurę wstawiania, aby zawierała odpowiednie klucze obce, a teraz po prostu dołączamy ponownie do tej tabeli podczas pobierania wyników do użytkowników. Ta tabela z łatwością przyczyniła się do 80% wiadomości, które musieliśmy przetworzyć w ciągu jednego dnia.
Przetwarzamy ~ 1 mln wiadomości dziennie (bez stołu mobilnego), a zdecydowana większość (99% +) naszych wiadomości jest przetwarzana w ramach naszego celu. Nadal mamy sporadyczne wartości odstające, ale biorąc pod uwagę rzadki charakter tego, że uważa się to za dopuszczalne.
Czynniki przyczyniające się:
Znalazłem błąd we wspomnianej wcześniej procedurze czyszczenia konwersacji, który w rzeczywistości nie czyścił właściwie rozmów i przedwcześnie je zakończył. Spowodowało to, że liczba naszych sysdesend nigdy nie będzie większa niż kilka tysięcy (większość z nich wynika z użycia lewy 150).
Kursory w wyzwalaczach wydawały się blokować bardziej niż oczekiwano (nawet przy statycznym, tylko do przodu). usunięcie ich wydaje się sprawić, że blokady, które widzimy w WYŚLIJ KONWERSACJĘ, są bardziej przejściowe (lub przynajmniej czasy, które widzimy, są znacznie niższe).
Zasadniczo uruchomiliśmy dwa rozwiązania obok siebie (backend rozwiązania Service Broker (do testowania pod obciążeniem produkcyjnym)) i obecne rozwiązanie (straszne zapytanie obejmujące wiele tabel).
Dodatkową korzyścią jest to, że ujawniono problem czyszczenia rekordów Ghost i chociaż nie było go w tabelach Service Broker (system lub kolejka), jest ono dość powszechne w naszym systemie, a objawy bardzo dobrze pokrywają się z naszą „bez wyraźnej przyczyny” problemy, których czasami doświadczamy. Trwa dochodzenie w tej sprawie, staramy się znaleźć tabele, które się do tego przyczyniają i prawdopodobnie rutynowo odbudujemy ich indeksy.
Dziękuję raz jeszcze.
źródło