Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

Cześć wszystkim! Nazywam się Sergey Kostanbaev, na Giełdzie rozwijam rdzeń systemu transakcyjnego.

Kiedy hollywoodzkie filmy pokazują nowojorską giełdę, zawsze wygląda to tak: tłumy ludzi, wszyscy coś krzyczą, machają papierami, panuje kompletny chaos. Coś takiego nigdy nie miało miejsca na moskiewskiej giełdzie, ponieważ handel od samego początku odbywał się drogą elektroniczną i opierał się na dwóch głównych platformach – Spectra (rynek forex) i ASTS (rynek walutowy, giełdowy i pieniężny). A dzisiaj chcę porozmawiać o ewolucji architektury systemu transakcyjno-rozliczeniowego ASTS, o różnych rozwiązaniach i ustaleniach. Historia będzie długa, dlatego musiałam podzielić ją na dwie części.

Jesteśmy jedną z niewielu giełd na świecie, która handluje aktywami wszystkich klas i zapewnia pełen zakres usług giełdowych. Przykładowo w ubiegłym roku zajęliśmy drugie miejsce na świecie pod względem wolumenu obrotu obligacjami, 25 miejsce wśród wszystkich giełd, 13 miejsce pod względem kapitalizacji wśród giełd publicznych.

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

Dla profesjonalnych uczestników handlu krytyczne znaczenie mają takie parametry, jak czas reakcji, stabilność rozkładu czasu (jitter) i niezawodność całego kompleksu. Obecnie przetwarzamy dziesiątki milionów transakcji dziennie. Przetwarzanie każdej transakcji przez jądro systemu zajmuje dziesiątki mikrosekund. Oczywiście operatorzy komórkowi w sylwestra lub same wyszukiwarki mają większe obciążenie pracą niż nasza, ale wydaje mi się, że pod względem obciążenia pracą w połączeniu z wyżej wymienionymi cechami niewielu może się z nami równać. Jednocześnie ważne jest dla nas, aby system nie zwalniał ani na sekundę, działał absolutnie stabilnie, a wszyscy użytkownicy mieli równe szanse.

Trochę historii

W 1994 roku na Moskiewskiej Międzybankowej Giełdzie Walutowej (MICEX) uruchomiono australijski system ASTS i od tego momentu można policzyć historię rosyjskiego handlu elektronicznego. W 1998 roku zmodernizowano architekturę giełdy, wprowadzając handel internetowy. Od tego czasu tempo wdrażania nowych rozwiązań i zmian architektonicznych we wszystkich systemach i podsystemach tylko nabiera tempa.

W tamtych latach system wymiany pracował na sprzęcie hi-end – ultra niezawodnych serwerach HP Superdome 9000 (zbudowanych na bazie PA-RISC), w którym zduplikowano absolutnie wszystko: podsystemy wejścia/wyjścia, sieć, pamięć RAM (w rzeczywistości była to macierz RAM typu RAID), procesory (z możliwością wymiany podczas pracy). Można było zmienić dowolny komponent serwera bez zatrzymywania maszyny. Polegaliśmy na tych urządzeniach i uznaliśmy je za praktycznie niezawodne. System operacyjny był systemem HP UX podobnym do Uniksa.

Jednak od około 2010 roku pojawiło się zjawisko zwane handlem o wysokiej częstotliwości (HFT), czyli handlem o wysokiej częstotliwości – po prostu robotami giełdowymi. W ciągu zaledwie 2,5 roku obciążenie naszych serwerów wzrosło 140 razy.

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

Przy starej architekturze i sprzęcie nie dało się wytrzymać takiego obciążenia. Trzeba było się jakoś przystosować.

początek

Zgłoszenia do systemu wymiany można podzielić na dwa typy:

  • Transakcje. Jeśli chcesz kupić dolary, akcje lub coś innego, wysyłasz transakcję do systemu transakcyjnego i otrzymujesz odpowiedź o powodzeniu.
  • Prośby o informacje. Jeśli chcesz poznać aktualną cenę, przejrzyj księgę zamówień lub indeksy, a następnie wyślij prośby o informacje.

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

Schematycznie rdzeń systemu można podzielić na trzy poziomy:

  • Poziom klienta, na którym pracują brokerzy i klienci. Wszystkie współdziałają z serwerami dostępowymi.
  • Serwery bramowe to serwery buforujące, które lokalnie przetwarzają wszystkie żądania informacji. Chcesz wiedzieć, po jakiej cenie obecnie notowane są akcje Sbierbanku? Żądanie trafia do serwera dostępowego.
  • Ale jeśli chcesz kupić akcje, żądanie trafia do centralnego serwera (Trade Engine). Dla każdego rodzaju rynku jest jeden taki serwer, odgrywają one kluczową rolę, to dla nich stworzyliśmy ten system.

Rdzeniem systemu transakcyjnego jest sprytna baza danych przechowywana w pamięci, w której wszystkie transakcje są transakcjami wymiany. Baza została napisana w C, jedynymi zewnętrznymi zależnościami była biblioteka libc i nie było w ogóle dynamicznej alokacji pamięci. Aby skrócić czas przetwarzania, system zaczyna od statycznego zestawu tablic i statycznej relokacji danych: najpierw do pamięci ładowane są wszystkie dane z bieżącego dnia i nie jest wykonywany dalszy dostęp do dysku, cała praca odbywa się wyłącznie w pamięci. Kiedy system się uruchamia, wszystkie dane referencyjne są już posortowane, więc wyszukiwanie przebiega bardzo sprawnie i zajmuje niewiele czasu. Wszystkie tabele są wykonane z natrętnych list i drzew dla dynamicznych struktur danych, dzięki czemu nie wymagają alokacji pamięci w czasie wykonywania.

Przyjrzyjmy się pokrótce historii rozwoju naszego systemu transakcyjnego i rozliczeniowego.
Pierwsza wersja architektury systemu transakcyjno-rozliczeniowego została zbudowana w oparciu o tzw. interakcję uniksową: wykorzystano pamięć współdzieloną, semafory i kolejki, a każdy proces składał się z jednego wątku. Podejście to było powszechne na początku lat 1990.

Pierwsza wersja systemu zawierała dwa poziomy Gatewaya oraz centralny serwer systemu transakcyjnego. Przebieg pracy wyglądał następująco:

  • Klient wysyła żądanie, które dociera do Bramy. Sprawdza ważność formatu (ale nie samych danych) i odrzuca nieprawidłowe transakcje.
  • Jeśli wysłano żądanie informacji, jest ono realizowane lokalnie; jeśli mówimy o transakcji, to zostaje ona przekierowana na serwer centralny.
  • Następnie silnik transakcyjny przetwarza transakcję, modyfikuje pamięć lokalną i wysyła odpowiedź na transakcję oraz samą transakcję w celu replikacji przy użyciu oddzielnego silnika replikacji.
  • Gateway odbiera odpowiedź z węzła centralnego i przekazuje ją do klienta.
  • Po pewnym czasie Gateway odbiera transakcję poprzez mechanizm replikacji i tym razem realizuje ją lokalnie, zmieniając swoje struktury danych tak, aby przy kolejnych żądaniach informacji wyświetlały się najnowsze dane.

W rzeczywistości opisuje model replikacji, w którym Gateway całkowicie replikuje działania wykonywane w systemie transakcyjnym. Oddzielny kanał replikacji zapewniał realizację transakcji w tej samej kolejności na wielu węzłach dostępowych.

Ponieważ kod był jednowątkowy, do obsługi wielu klientów zastosowano klasyczny schemat z forkami procesów. Jednak rozwidlenie całej bazy danych było bardzo kosztowne, dlatego zastosowano lekkie procesy usługowe, które zbierały pakiety z sesji TCP i przesyłały je do jednej kolejki (kolejka komunikatów SystemV). Gateway i Trade Engine działały tylko z tą kolejką, pobierając stamtąd transakcje do realizacji. Nie było już możliwości przesłania na nią odpowiedzi, gdyż nie było jasne, który proces serwisowy powinien ją przeczytać. Uciekliśmy się więc do triku: każdy rozwidlony proces tworzył dla siebie kolejkę odpowiedzi, a kiedy żądanie przyszło do kolejki przychodzącej, natychmiast dodawany był do niego znacznik kolejki odpowiedzi.

Ciągłe kopiowanie dużych ilości danych z kolejki do kolejki stwarzało problemy, szczególnie typowe dla żądań informacji. Dlatego zastosowaliśmy kolejny trik: oprócz kolejki odpowiedzi każdy proces tworzył także pamięć współdzieloną (SystemV Shared Memory). Umieszczano w nim same paczki, a w kolejce przechowywany był jedynie znacznik umożliwiający odnalezienie oryginalnej paczki. Pomogło to w przechowywaniu danych w pamięci podręcznej procesora.

SystemV IPC zawiera narzędzia do przeglądania stanu obiektów kolejek, pamięci i semaforów. Aktywnie wykorzystywaliśmy to, aby zrozumieć, co dzieje się w systemie w danym momencie, gdzie gromadziły się pakiety, co zostało zablokowane itp.

Pierwsze ulepszenia

Przede wszystkim pozbyliśmy się bramy jednoprocesowej. Jego istotną wadą było to, że mógł obsłużyć jedną transakcję replikacji lub jedno żądanie informacji od klienta. W miarę wzrostu obciążenia brama będzie potrzebowała więcej czasu na przetwarzanie żądań i nie będzie w stanie przetworzyć przepływu replikacji. Dodatkowo, jeśli klient wysłał transakcję, wystarczy sprawdzić jej ważność i przekazać ją dalej. Dlatego zastąpiliśmy pojedynczy proces Gateway wieloma komponentami, które mogą działać równolegle: wielowątkowe procesy informacyjne i transakcyjne działające niezależnie od siebie w obszarze pamięci współdzielonej przy użyciu blokowania RW. Jednocześnie wprowadziliśmy procesy wysyłki i replikacji.

Wpływ handlu o wysokiej częstotliwości

Powyższa wersja architektury istniała do 2010 roku. Tymczasem nie byliśmy już zadowoleni z wydajności serwerów HP Superdome. Poza tym architektura PA-RISC była praktycznie martwa, sprzedawca nie zaoferował żadnych znaczących aktualizacji. W rezultacie zaczęliśmy przechodzić z HP UX/PA RISC na Linux/x86. Przejście rozpoczęło się od dostosowania serwerów dostępowych.

Dlaczego musieliśmy ponownie zmienić architekturę? Faktem jest, że handel o wysokiej częstotliwości znacząco zmienił profil obciążenia rdzenia systemu.

Załóżmy, że mamy małą transakcję, która spowodowała znaczną zmianę ceny – ktoś kupił za pół miliarda dolarów. Po kilku milisekundach wszyscy uczestnicy rynku zauważają to i zaczynają wprowadzać korektę. Naturalnie żądania ustawiają się w ogromnej kolejce, której czyszczenie zajmie systemowi dużo czasu.

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

W tym przedziale 50 ms średnia prędkość wynosi około 16 tysięcy transakcji na sekundę. Jeśli zmniejszymy okno do 20 ms, otrzymamy średnią prędkość 90 tys. transakcji na sekundę, przy czym w szczycie będzie to 200 tys. transakcji. Innymi słowy, obciążenie nie jest stałe, z nagłymi impulsami. A kolejka żądań musi być zawsze szybko obsłużona.

Ale dlaczego w ogóle jest kolejka? Zatem w naszym przykładzie wielu użytkowników zauważyło zmianę ceny i odpowiednio wysłało transakcje. Przychodzą do Gateway, serializuje je, ustala określoną kolejność i wysyła do sieci. Routery tasują pakiety i przekazują je dalej. Czyja paczka dotarła jako pierwsza, ta transakcja „wygrała”. W rezultacie klienci giełdy zaczęli zauważać, że jeśli ta sama transakcja została wysłana z kilku Gatewayów, wówczas wzrosły szanse na jej szybką realizację. Wkrótce roboty giełdowe zaczęły bombardować Gateway żądaniami i ruszyła lawina transakcji.

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

Nowa runda ewolucji

Po szeroko zakrojonych testach i badaniach przeszliśmy na jądro systemu operacyjnego czasu rzeczywistego. W tym celu wybraliśmy RedHat Enterprise MRG Linux, gdzie MRG oznacza siatkę przesyłania wiadomości w czasie rzeczywistym. Zaletą poprawek w czasie rzeczywistym jest optymalizacja systemu pod kątem najszybszego możliwego wykonania: wszystkie procesy są ułożone w kolejce FIFO, rdzenie można izolować, nie ma wyrzutów, wszystkie transakcje są przetwarzane w ścisłej kolejności.

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1
Czerwony - praca z kolejką w zwykłym jądrze, zielony - praca w jądrze czasu rzeczywistego.

Jednak osiągnięcie małych opóźnień na zwykłych serwerach nie jest takie proste:

  • Mocno przeszkadza tryb SMI, który w architekturze x86 jest podstawą do pracy z ważnymi urządzeniami peryferyjnymi. Przetwarzanie wszelkiego rodzaju zdarzeń sprzętowych oraz zarządzanie komponentami i urządzeniami odbywa się przez oprogramowanie w tzw. przezroczystym trybie SMI, w którym system operacyjny w ogóle nie widzi, co robi oprogramowanie. Z reguły wszyscy główni dostawcy oferują specjalne rozszerzenia dla serwerów oprogramowania sprzętowego, które pozwalają zmniejszyć ilość przetwarzania SMI.
  • Nie powinno być dynamicznej kontroli częstotliwości procesora, prowadzi to do dodatkowych przestojów.
  • Kiedy dziennik systemu plików jest opróżniany, w jądrze zachodzą pewne procesy, które powodują nieprzewidywalne opóźnienia.
  • Musisz zwrócić uwagę na takie rzeczy, jak powinowactwo procesora, powinowactwo przerwań, NUMA.

Muszę powiedzieć, że temat konfiguracji sprzętu i jądra Linuksa do przetwarzania w czasie rzeczywistym zasługuje na osobny artykuł. Spędziliśmy dużo czasu na eksperymentach i badaniach, zanim osiągnęliśmy dobry wynik.

Przechodząc z serwerów PA-RISC na x86, praktycznie nie musieliśmy zbytnio zmieniać kodu systemu, po prostu go dostosowaliśmy i przekonfigurowaliśmy. Jednocześnie naprawiliśmy kilka błędów. Na przykład szybko wyszły na jaw konsekwencje faktu, że PA RISC był systemem Big endian, a x86 był systemem Little endian: na przykład dane zostały odczytane niepoprawnie. Bardziej skomplikowany błąd polegał na tym, że używa PA RISC konsekwentnie konsekwentny (Kolejno spójne) dostępu do pamięci, podczas gdy x86 może zmienić kolejność operacji odczytu, więc kod, który był absolutnie poprawny na jednej platformie, został uszkodzony na innej.

Po przejściu na x86 wydajność wzrosła prawie trzykrotnie, średni czas przetwarzania transakcji spadł do 60 μs.

Przyjrzyjmy się teraz bliżej, jakie kluczowe zmiany zostały wprowadzone w architekturze systemu.

Gorący, rezerwowy epicki

Przechodząc na serwery towarowe, zdawaliśmy sobie sprawę, że są one mniej niezawodne. Dlatego tworząc nową architekturę założyliśmy a priori możliwość awarii jednego lub większej liczby węzłów. Dlatego potrzebny był system gorącej rezerwy, który mógłby bardzo szybko przełączyć się na maszyny zapasowe.

Ponadto istniały inne wymagania:

  • W żadnym wypadku nie możesz stracić przetworzonych transakcji.
  • System musi być całkowicie przezroczysty dla naszej infrastruktury.
  • Klienci nie powinni widzieć zerwanych połączeń.
  • Rezerwacje nie powinny wprowadzać znaczących opóźnień, ponieważ jest to czynnik krytyczny dla wymiany.

Tworząc system hot standby nie braliśmy pod uwagę takich scenariuszy jak podwójne awarie (np. przestała działać sieć na jednym serwerze i zawiesił się serwer główny); nie wziął pod uwagę możliwości wystąpienia błędów w oprogramowaniu, ponieważ są one wykrywane podczas testowania; i nie wziął pod uwagę nieprawidłowej pracy sprzętu.

W rezultacie doszliśmy do następującego schematu:

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

  • Serwer główny współpracował bezpośrednio z serwerami Gateway.
  • Wszystkie transakcje otrzymane na serwerze głównym były natychmiast replikowane na serwer zapasowy za pośrednictwem osobnego kanału. Arbiter (gubernator) koordynował zmianę w przypadku pojawienia się jakichkolwiek problemów.

    Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

  • Serwer główny przetwarzał każdą transakcję i czekał na potwierdzenie z serwera zapasowego. Aby zminimalizować opóźnienia, uniknęliśmy oczekiwania na zakończenie transakcji na serwerze zapasowym. Ponieważ czas potrzebny na przebycie transakcji przez sieć był porównywalny z czasem realizacji, nie dodano żadnych dodatkowych opóźnień.
  • Mogliśmy jedynie sprawdzić status przetwarzania serwera głównego i zapasowego dla poprzedniej transakcji, a status przetwarzania bieżącej transakcji był nieznany. Ponieważ nadal korzystaliśmy z procesów jednowątkowych, oczekiwanie na odpowiedź z Backupu spowolniłoby cały proces przetwarzania, dlatego poszliśmy na rozsądny kompromis: sprawdziliśmy wynik poprzedniej transakcji.

Ewolucja architektury systemu handlu i rozliczeń moskiewskiej giełdy. Część 1

Schemat działał w następujący sposób.

Załóżmy, że główny serwer przestaje odpowiadać, ale bramy nadal się komunikują. Na serwerze zapasowym nastąpi przekroczenie limitu czasu, kontaktuje się on z Gubernatorem, który przydziela mu rolę serwera głównego, a wszystkie Bramy przełączają się na nowy serwer główny.

Jeśli główny serwer powróci do trybu online, powoduje to również wewnętrzny przekroczenie limitu czasu, ponieważ przez określony czas nie było żadnych połączeń z serwerem z bramki. Następnie zwraca się także do Wojewody i ten wyklucza go z planu. Dzięki temu giełda współpracuje z jednym serwerem do końca okresu handlowego. Ponieważ prawdopodobieństwo awarii serwera jest dość niskie, schemat ten uznano za całkiem akceptowalny, nie zawierał skomplikowanej logiki i był łatwy do przetestowania.

Aby być kontynuowane.

Źródło: www.habr.com

Dodaj komentarz