Pamięć NUMA W przypadku dużych serwerów baz danych decyduje o tym, jak blisko wymaganej pamięci działają wątki oraz w jakim stopniu opóźnienia wpływają na czasy odpowiedzi i przepustowość. Celowo dostosowuję przydział procesora, rozmieszczenie pamięci i wielkość obciążenia, ograniczam odległe dostępy, a tym samym osiągam niezawodną, przewidywalną Wydajność.
Punkty centralne
- Topologia Zrozumieć: uwzględnić w sposób ukierunkowany węzły, rdzenie, pamięć RAM i połączenia międzysystemowe.
- Zasady Wybierz odpowiednią opcję: Strict, Preferred, Interleave w zależności od docelowego obciążenia.
- Affinität Wdrożenie: lokalne przypisanie wątków, sygnałów IRQ i pamięci.
- Maszyny wirtualne zgodnie z rozmiarem węzła: umieścić vCPU i pamięć RAM w jednym węźle NUMA.
- Monitoring Przeprowadzić: pomiary odczytów zdalnych, opóźnienia P99 oraz obciążenia węzłów.
Zrozumieć topologię NUMA
Każdą optymalizację rozpoczynam od Topologia: Ile jest węzłów NUMA, jak rozłożone są jądra, w jaki sposób pamięć RAM jest podłączona do gniazd oraz ile kosztują operacje dostępu do sieci połączeń. Dostęp do pamięci lokalnej zajmuje znacznie mniej czasu niż dostęp poza granicami węzła, dlatego unikam niepotrzebnych Zdalny-sposoby. Duże serwery baz danych zyskują, gdy planuję obciążenia w taki sposób, aby wątki i dane pozostawały na tym samym węźle. Jeśli aktywny zestaw danych nie mieści się w jednym węźle, celowo planuję jego rozkład, zamiast pozostawiać to domyślnemu zachowaniu. W ten sposób utrzymuję Opóźnienie niskie i zapewniają równomierną wydajność nawet przy dużym obciążeniu.
Prawidłowy wybór ustawień BIOS-u i sprzętu
W BIOS-ie sprawdzam, czy Przeplatanie węzłów jest wyłączona, aby zachować separację NUMA. Kanały pamięci przypisuję symetrycznie do każdego gniazda i zwracam uwagę na konfigurację (1DPC vs. 2DPC), aby nie doszło do niepotrzebnego spadku częstotliwości taktowania i przepustowości. Funkcje takie jak Stany C a w przypadku agresywnych trybów oszczędzania energii ustawiam cele opóźnienia na bardziej konserwatywne, aby rdzenie nie musiały ciągle się budzić. SMT/Gwintowanie nadprądowe Oceniam to w zależności od obciążenia: w przypadku obciążeń OLTP silnie zależnych od pamięci ograniczam liczbę równoległych wątków SMT na rdzeń, aby zmniejszyć obciążenie pamięci podręcznej i zmienność. Sprawdzam również, czy urządzenia PCIe (karty sieciowe, NVMe) są podłączone lokalnie do każdego gniazda, aby ich IRQ a ścieżki DMA nie przebiegają w poprzek sieci Interconnect. Kto dokładnie to zaplanuje, stworzy podstawę, na której zasady i powiązania będą mogły w pełni zadziałać.
Właściwy dobór zasad zarządzania pamięcią
Wybór Polityka określa, z którego węzła jądro przydziela pamięć oraz jak wyglądają rozwiązania awaryjne. Opcja „Strict” ustanawia ścisłe ograniczenia i przerywa alokację, jeśli węzeł docelowy nie ma wolnego miejsca; nadaje to priorytet Wydajność o elastyczności. Strategia „Preferred” utrzymuje preferowany węzeł, ale w przypadku niedoboru zasobów przechodzi na inne węzły, oferując w ten sposób kompromisowe rozwiązanie. Strategia „Interleave” rozdziela strony metodą „round-robin” między kilka węzłów, co może być sensownym rozwiązaniem w przypadku bardzo dużych zbiorów danych o równomiernym obciążeniu. W przypadku wielu baz danych lepszym rozwiązaniem jest zazwyczaj strategia lokalna oparta na metodzie „Preferred” lub „Strict”. Wybór.
| Polityka | Prowadzenie | Typowe zastosowanie | Zalety | Ryzyko |
|---|---|---|---|---|
| Ścisły | Pobiera dane z pamięci wyłącznie z węzła docelowego, w przeciwnym razie zgłasza błąd | Krytyczne w sensie latentnym Bazy danych z jasnym planem węzłów | Maksymalnie lokalne Dostępy, przewidywalne opóźnienia | Alokacja może się nie powieść, jeśli węzeł jest pełny |
| Preferowane | Węzeł preferowany, z możliwością przełączenia na inny | Ogólne Obciążenia przy zmiennym obciążeniu | Dobra dostępność przy akceptowalnej elastyczności | Większy udział pracy zdalnej w sytuacji niedoboru |
| Interleave | Algorytm Round-Robin obejmujący wiele węzłów | Bardzo duże, szeroko stosowane Dane | Rozłożone obciążenie kilku węzłów | Słabsza lokalizacja, potencjalnie większe opóźnienie |
Wątki, przypisanie procesora i przypisanie pamięci
Przypisuję wątki do rdzeni węzła docelowego, przydzielam pamięć za pomocą numactl i dostosowuję przerwy IRQ tak, aby Dane pozostać lokalnie. To połączenie powinowactwa procesora (CPU affinity) i powiązania z pamięcią (memory binding) ogranicza kosztowne odczyty zdalne i sprawia, że rozkład czasu wykonania jest bardziej zwarty. Aby uzyskać szczegółową kontrolę, stosuję zasady na poziomie procesów lub wątków i utrzymuję pulę buforów jak najbliżej aktywnych wątków roboczych. Kto chce zagłębić się w ten temat, znajdzie praktyczne wskazówki dotyczące Przynależność procesora, które można zastosować bezpośrednio na hostach produkcyjnych. W ten sposób zapewniam spójność Opóźnienia nawet wtedy, gdy system jest mocno obciążony.
Priorytet dla lokalnych zestawów „Hotsets”
Wyróżniam zestawy „Hotsets” z Obciążenie pracą i umieszczaj je ściśle lokalnie, podczas gdy dane rzadko używane mogą być przechowywane w sposób bardziej elastyczny. Dzięki takiemu ustaleniu priorytetów ścieżki podstawowe pozostają blisko pamięci RAM węzła. Wraz ze wzrostem obciążenia rozwiązanie skaluje się płynnie, ponieważ kosztowne ścieżki nadal działają lokalnie. Bez tego porządku krzywa opóźnień zaczyna się pogarszać, gdy tylko wątki coraz częściej uzyskują dostęp do danych w różnych węzłach. Jasna Wiązanie skutecznie zapobiega właśnie takiemu zachowaniu.
Połączenie NUMA pamięci masowej i sieciowej
Organizuję Karty sieciowe oraz NVMe-Urządzenia przypisuję celowo do gniazd i kieruję ich sygnały IRQ do lokalnych rdzeni. Sterowanie odbiorem/transmisją (RSS/RPS/XPS) utrzymuję spójnie dla każdego węzła, tak aby pakiety były przetwarzane tam, gdzie działają wątki bazy danych. W przypadku NVMe korzystam z kilku kolejek na rdzeń i przypisuję wątki IO lokalnie, dzięki czemu ścieżki logów i danych nie przechodzą przez interkonekt. W celu replikacji rozdzielam ścieżki sieciowe na poszczególne węzły, tak aby przychodzące strumienie WAL/Redo trafiały lokalnie. W ten sposób pozostają IO– a ścieżki procesora są zgodne, a baza danych nie marnuje cykli na niepotrzebne kopie w całej sieci pamięci.
Planowanie maszyn wirtualnych na poziomie węzłów
Dopasowuję wymiary maszyn wirtualnych tak, aby liczba procesorów vCPU i pamięć RAM mieściły się w jednym fizycznym węźle NUMA, ponieważ pozwala to zmniejszyć Opóźnienie oraz ruch międzywęzłowy. Maszyny wirtualne typu „wide”, które są większe niż jeden węzeł, nieuchronnie rozpraszają dostępy do pamięci, tracąc tym samym przewidywalność. Jeśli maszyna wirtualna musi być większa, planuję vNUMA w sposób jawny i dbam o symetryczny podział między węzłami. Jeśli chodzi o stronę hosta, unikam nadmiernego przydziału zasobów w przypadku obciążeń wymagających niskiego opóźnienia i rezerwuję pamięć lokalną dla każdej maszyny wirtualnej. Szybki przegląd fizycznej struktury węzłów zapewnia „Planowanie węzłów NUMA“, co ułatwia podejmowanie decyzji dotyczących rozmiaru maszyny wirtualnej oraz Błąd zapobiega przemieszczaniu się.
Należy zwrócić uwagę na ustawienia hiperwizora
Sprawdzam, w jaki sposób hiperwizor przedstawia vNUMA, i zachowuję przyporządkowanie grup vCPU do fizycznych Rdzenie spójnie. Dodatkowo dbam o to, by topologia NUMA maszyny wirtualnej odpowiadała topologii hosta, dzięki czemu harmonogram może działać lokalnie. Rezerwacje pamięci i reguły antyafinności ograniczam do minimum, ale stosuję je tak rygorystycznie, jak to konieczne. Wysoką gęstość maszyn wirtualnych na jednym gnieździe wolę zastąpić rozmieszczeniem w pobliżu węzłów. W ten sposób zapewniam Zdalny-Ogranicz liczbę operacji dostępu do minimum i zapewnij stabilność ścieżek wejścia/wyjścia.
Kontenery i praktyka orkiestracji
W pojemnikach umieszczam zestaw procesorów-Spójność granic: procesory i powiązane maski pamięci (cpuset.cpus, cpuset.mems) są ze sobą powiązane. Segmenty i jednostki systemd otrzymują stałe przypisania procesora, dzięki czemu jądro rzeczywiście egzekwuje preferencje pamięciowe. W warstwach orkiestracji planuję pody/usługi blisko węzła, stosuję oceny topologii i statyczny przydział procesorów, aby obciążenie nie przechodziło między węzłami. Strony typu „Huge Pages” deklaruję jawnie dla każdego poda/kontenera i utrzymuję ich rozmiar oraz liczbę na stałym poziomie dla każdego węzła. Ważne: procesy infrastrukturalne i pomocnicze (rejestrowanie, sidecary, kopie zapasowe) przypisuję do innych rdzeni lub nawet do drugiego węzła NUMA, aby nie zakłócać operacji typu „hotset” w bazie danych.
Równoważenie NUMA i optymalizacja systemu operacyjnego
Automatyczne równoważenie NUMA może lokalne Dostępy poprawić, gdy obciążenia się przemieszczają lub fazy ulegają znacznym zmianom. Korzystam z tego w sposób celowy, ale obserwuję, czy przenoszenie stron tam i z powrotem nie przynosi więcej szkody niż pożytku. Procesy o stałej strukturze i wyraźnej przynależności często zyskują na ręcznie ustawionych zasadach zamiast ciągłego przenoszenia. Parametry jądra, sterowanie IRQ oraz przezroczyste strony Huge Pages sprawdzam zawsze w kontekście bazy danych i platformy. Jako punkt wyjścia pomaga mi to Równoważenie NUMA-Przewodnik po testowaniu ustawień krok po kroku oraz rozproszenie zmniejszenia opóźnień.
Celowe wykorzystanie stron typu „Huge Pages”
Korzystam z funkcji Huge Pages, aby ograniczyć liczbę nieudanych odwołań do TLB oraz duże Pamięćbardziej efektywnie obsługiwać poszczególne obszary. W przypadku serwerów baz danych rezerwuję strony z wyprzedzeniem, przypisuję je do węzłów i sprawdzam, czy instancja faktycznie z nich korzysta. Często wyłączam Transparent Huge Pages przy określonych celach dotyczących opóźnień i ustawiam statyczne Huge Pages, aby alokacja pozostała deterministyczna. Decydujące znaczenie ma jednak bliskość węzła NUMA; Huge Pages wzmacniają dobrą strategię, ale jej nie zastępują. Kto to ignoruje, ten raczej nie zyska Wydajność i naraża się na skutki uboczne związane z paginacją.
Wymiarowanie baz danych: pula buforów i obciążenie robocze
Planuję aktywną objętość pracy w taki sposób, aby bufor puli, pamięć podręczna blokad i planów oraz najczęściej używane Tabele zmieścić się w jednym węźle. W przypadku bardzo dużych instancji dzielę usługi lub fragmenty między węzły, zamiast rozciągać jedną ogromną, monolityczną instancję na wszystkie węzły. W przypadku OLTP utrzymuję pulę buforów na każdym węźle na kompaktowym poziomie i priorytetowo traktuję lokalne współczynniki trafień. W przypadku skanowania OLAP interleave może być przydatne w szczególnych sytuacjach, gdy ilość danych jest ogromna i równomierna. Bez tej dyscypliny rośnie Połączenie-ruch i zużywa rezerwy właśnie wtedy, gdy występują szczyty obciążenia.
Sposoby związane z bazami danych
Biorę pod uwagę model procesów i wątków silnika: PostgreSQL wykorzystuje procesy, dlatego uruchamiam instancję główną, Autovacuum i Checkpointer osobno dla każdego węzła i utrzymuję shared_buffers lokalnie dla każdego shardu. W przypadku MySQL/InnoDB tworzę folder instancje puli buforów na węzłach oraz dostosuj lokalnie wątki IO i moduły zapisujące logi. SQL Server korzysta z dostosowanego modelu Soft-NUMA oraz schematu przydziału, który rozdziela harmonogramy i grupy pamięci między węzły fizyczne. Oracle-Instancje konfiguruję z wykorzystaniem lokalnych stron dużych (Large Pages) i dzielę serwery robocze oraz serwery wejścia/wyjścia (IO) między węzły. Ogólnie ograniczam rywalizację o areny w alokatorze (np. jemalloc) poprzez areny dostosowane do architektury NUMA i dbam o to, aby Menedżer blokad a punkty newralgiczne związane z blokadami pozostają lokalne dzięki zastosowaniu partycjonowania i shardingu wzdłuż węzłów.
Monitorowanie: wskaźniki, które mają znaczenie
Mierzę odczyty zdalne, ruch międzywęzłowy, liczbę błędów stron na węzeł oraz wskaźnik P99-Opóźnienie odpowiednich zapytań. Dodatkowo monitoruję obciążenie procesora dla poszczególnych węzłów, wskaźniki NUMA Miss oraz odsetek lokalnych dostępów do pamięci. Ten widok pokazuje, czy polityka działa, czy też wątki w sposób niekontrolowany uzyskują dostęp do odległych stron. Koreluję szczyty obciążenia z decyzjami harmonogramu, zdarzeniami migracji oraz błędami alokacji. Dopiero te wskaźniki potwierdzają, że Polityka nie tylko w laboratorium, ale na stałe w systemie produkcyjnym.
Strategia testowa i wdrożenie
Przeprowadzam testy etapami: najpierw mikrotesty wydajności dotyczące Szerokość pasma oraz opóźnienie na węzeł, a następnie realistyczne obciążenia z „zimnymi” i „ciepłymi” pamięciami podręcznymi. Obciążenie zwiększam stopniowo, mierzę wartości P95/P99/P99,9 i obserwuję rozkład wyników, a nie tylko średnie. Dokumentuję każdą zmianę (politykę, powinowactwa, strony typu Huge Pages, przekierowanie IRQ) i porównuję wyniki testów A/B w identycznych warunkach ramowych. Przed wdrożeniem definiuję Kryteria anulowania oraz plan awaryjny, dzięki któremu w razie regresji będę mógł szybko przywrócić poprzednią konfigurację. Krótki test wytrzymałościowy pod stałym obciążeniem pozwala sprawdzić Drift oraz migracje, które w krótkich okresach pozostają niewidoczne.
Procedura krok po kroku
Najpierw wprowadzam Topologia: Liczba węzłów, przypisanie rdzeni, kanały pamięci i interkonekt. Następnie określam docelowe obciążenie dla każdego węzła i sprawdzam, czy zmieszczą się w nim zestawy „hotsets”. W kolejnym kroku ustawiam powinowactwo procesora, kierowanie IRQ oraz wiązanie pamięci na poziomie procesu lub wątku. Następnie włączam lub wyłączam równoważenie NUMA w zależności od dynamiki obciążenia i w razie potrzeby rezerwuję ogromne strony pamięci na każdy węzeł. Na koniec weryfikuję wynik za pomocą powtarzalnych testów obciążeniowych i monitoruję Kluczowe dane w trybie ciągłym.
Przykłady z praktyki i przeszkody
Instancja OLTP z wieloma krótkimi transakcjami odnotowuje wymierną poprawę wydajności, gdy ustawię liczbę wątków roboczych i pulę buforów na Węzeł i ustawić opcję „Strict“ lub „Preferred”. Magazyn danych z szerokimi skanami może odnieść korzyści z interleave, jeśli dane są wykorzystywane bardzo równomiernie, a węzły są dobrze obciążone. Maszyny wirtualne stają się znacznie trudniejsze do planowania, gdy tylko wykraczają poza granice węzłów, a hiperwizor przydziela pamięć w sposób rozproszony. Często obserwuję, że pojedyncza „rozległa” maszyna wirtualna przeciąża interkonekt, spowalniając tym samym sąsiednie maszyny wirtualne. Efekty te zanikają, gdy tylko przejdę na lokalną Przydział i powrócę do poprawnej konfiguracji vNUMA.
Scenariusze błędów i antywzorce
Z Ścisły zwiększam ryzyko niepowodzenia alokacji i uruchomienia mechanizmu OOM-Killer. Dlatego zapewniam wolne zasoby rezerwowe na węźle docelowym, monitoruję nieudane próby i definiuję rozwiązania awaryjne (np. ukierunkowaną zmianę rozmiaru poza godzinami szczytu). Transparent Huge Pages w zawsze-tryb powoduje w ścieżkach opóźnienia Defragmentacja i stajni – korzystam z rezerwacji statycznych lub włączam THP madvise. Automatyczne równoważenie NUMA może przenosić strony tam i z powrotem przy zmiennym obciążeniu; jeśli zauważę wzorce „page bounce”, ponownie ręcznie ustalam zasady. W maszynach wirtualnych Baloniarstwo a kompresja pamięci to zmora przewidywalności; w przypadku krytycznych baz danych wyłączam te funkcje. Migracje na żywo między węzłami planuję wyłącznie w ramach okien przestoju lub najpierw przenoszę dane po stronie bazy danych, aby interkonekt nie uległ wtórnemu przeciążeniu.
Planowanie zdolności produkcyjnych i rozwój
Planuję na każdy węzeł po Rezerwa Ustawiam 10–20 % na okresy szczytowego obciążenia, operacje Autovacuum/Compaction oraz okresowe zadania konserwacyjne. Gdy ilość danych rośnie, najpierw skaluję system wzdłuż węzłów (shardów/usług), zamiast ślepo powiększać całą pulę buforów. Zapobiegam cichemu „stopniowemu wzrostowi“ poprzez ustalenie sztywnych limitów dla poszczególnych węzłów oraz alertów uruchamianych, gdy tylko spadają lokalne wskaźniki trafień lub wzrasta udział danych zdalnych. Przy prognozowaniu na kolejne kwartały biorę pod uwagę nie tylko objętość danych, ale także Wskaźniki transakcji oraz zmiany w rozkładzie dostępu, ponieważ często powodują one przesunięcie zestawów najczęściej używanych (hotsetów) szybciej niż wynikałoby to wyłącznie z zapotrzebowania na pamięć. Dzięki temu platforma pozostaje stabilna, a rozbudowa odbywa się w sposób kontrolowany, bez poświęcania lokalności NUMA.
Krótki bilans
Optymalizuję duże serwery baz danych poprzez NUMA-Spójnie łączę topologię, zasady i wielkość obciążenia. Lokalne przypisanie pamięci zapewnia kluczowe milisekundy, podczas gdy nieplanowane dostępy zdalne powodują wzrost opóźnienia P99. W przyszłości planuję maszyny wirtualne tak, aby mieściły się w węzłach lub wyraźnie wykorzystywały vNUMA. Ustawienia systemu operacyjnego, powinowactwa i strony typu Huge Pages stosuję w sposób celowy, sprawdzam ich wpływ i wdrażam zmiany wyłącznie w oparciu o pomiary. Kto zastosuje się do tych wskazówek, osiągnie oczekiwane Wydajność składa się z nowoczesnego sprzętu i zapewnia niezawodną szybkość działania platform nawet przy dużym obciążeniu.


