OVH NEWS | AKTUALNOŚCI, INNOWACJE I TENDENCJE W IT


Najnowsze informacje o OVH












10/10/2017
Podziel się z innymi

Autor artykułu: Hugo Bonnaffé


Jak tworzymy w OVH codzienne kopie zapasowe miliona baz danych


Wybierając hosting WWW w OVH, dostajesz do dyspozycji co najmniej jedną bazę danych. Możesz także rozszerzyć swoją ofertę o Prywatny Serwer SQL, który umożliwia uruchomienie dowolnej ilości baz danych. Obecnie na naszych serwerach utrzymujemy ponad milion baz danych naszych klientów, w ramach tych dwóch rozwiązań, a wszystkie są objęte codzienną kopią zapasową, wykonywaną przez OVH. Taka ilość baz danych do skopiowania rodzi wiele wyzwań: jak uniknąć wzrostu obciążenia w infrastrukturze podczas wykonywania kopii? Która metoda wykonywania kopii będzie najefektywniejsza? Kiedy wykonywać kopie, aby nie odczuli tego klienci?





Kiedy wykonujemy kopie zapasowe?


Masowe wykonywanie kopii zapasowych (baz danych lub innego rodzaju danych) wiąże się ze wzrostem obciążenia infrastruktury: zwiększa się ilość zapytań Input/Output (I/O), ponieważ dane muszą zostać skopiowane oraz wzrasta zużycie łącza sieciowego, ze względu na przenoszenie danych w inną lokalizację, gdzie będą przechowywane.

Problem ten jest dobrze znany administratorom sieciowym, dlatego zwyczajowo kopie są wykonywane w nocy.

W przeszłości także w OVH wykonywaliśmy kopie nocą. Dla większości kont hostingowych w OVH, nocny spadek ruchu następuje w godzinach 01:00-07:00. W tym przedziale czasowym wykonywaliśmy więc kopie zapasowe.

Co nas skłoniło do zmiany? Metoda ta szybko pokazała swoje ograniczenia. W godzinach 01:00-07:00 nasz system monitoringu zmieniał kolor na czerwony. Zauważaliśmy zastoje. Wykonywanie zrzutów (eksporty baz danych SQL) zajmowało więcej czasu, co zagrażało jakości świadczonych przez nas usług, ponieważ proces kopiowania danych nie zawsze kończył się w określonym przez nas przedziale czasu. Oznaczało to, że infrastruktura musiała obsłużyć jednocześnie obciążenie związane z wykonywaniem backupów oraz wzrastającą w godzinach porannych liczbę użytkowników odwiedzających strony WWW. Nie mogliśmy na to pozwolić.

Skorzystaliśmy więc z innego sposobu - rozłożyliśmy tworzenie kopii zapasowych na cały dzień. Dzięki temu zachowujemy optymalną wydajność na hostingach WWW, bez względu na godzinę w ciągu dnia i w nocy.



Algorytm podziału zadań


Aby rozłożyć tworzenie kopii w sposób zrównoważony w ciągu dnia, musieliśmy przyporządkować każdą bazę danych do określonej godziny.

Nie mogliśmy zastosować poziomej fragmentacji («shardingu») wyłącznie na podstawie nazwy bazy. W całej infrastrukturze jest niezliczona liczba baz danych o nazwie «wordpress», «prestashop» oraz «test» czy «demo». Gdybyśmy uruchomili jednoczesny backup wszystkich baz «wordpress» o tej samej godzinie, nie byłby on optymalny i mógłby doprowadzić do przeciążenia infrastruktury.

Pomimo że nazwa instancji obsługującej bazę danych jest unikalna, nie mogliśmy wykonywać shardingu opartego wyłącznie na niej. Instancji jest dużo mniej niż baz danych. Zgodnie z prawem wielkich liczb, rozłożenie w ciągu dnia zadań backupowych na podstawie nazw instancji byłoby mniej równomierne, niż zaplanowanie tych zadań w oparciu o nazwy samych baz danych. Powiązaliśmy więc te dwie informacje i dziś do równomiernego rozłożenia zadań tworzących kopie używamy algorytmu opierającego się na nazwach baz danych oraz instancji.

Pozostało nam jedynie odnalezienie formuły, która umożliwi połączenie tego łańcucha znaków z czasem w ciągu dnia, czyli liczbą w przedziale od 1 do 1 440 (liczba minut w ciągu doby). Liczba 1 440 jest podzielna przez 16 (dziękujemy Babilończykom za wybranie 60 jako bazy do zliczania minut i sekund), więc użyliśmy prostej funkcji haszowania kryptograficznego (digest) szesnastkowego (sha512), aby wygenerować liczbę odpowiadająca momentowi wykonywania kopii:

int(hashlib.sha512(instance_name + "." + db_name).hexdigest()[:90], 16) % 1440

Jak widać na poniższym wykresie, kopie zapasowe są równomiernie rozłożone w ciągu doby.







Jak wykonujemy kopie zapasowe?


Istnieją dwa sposoby wykonywania backupów baz danych. Można eksportować dane w formacie SQL lub zapisywać bazy w formacie odczytywanym przez system zarządzania bazą danych (na przykład SGBD czy MySQL). Każdy z tych sposobów ma swoje zalety, wady oraz typowe przypadki zastosowań. Połączyliśmy oba te sposoby, żeby wykorzystać zalety każdego z nich.

Zrzuty (Dump)

Zrzut bazy danych to wygenerowany plik tekstowy z poleceniami SQL, który podczas ich wykonywania, odtwarza bazę danych w stanie, w jakim znajdowała się ona w momencie eksportu. Zaletą tej metody jest możliwość migracji danych do innych wersji SGBD lub do innych silników. Ten sposób eksportowania danych pozwala na ręczne modyfikowanie pliku przed jego ponownym zaimportowaniem. Jest to przydatne w chwili, gdy chcemy sklonować środowisko produkcyjne, na potrzeby testów, z pominięciem niektórych tabel bazy.

Ze względu na szerokie zastosowanie tej metody, w OVH udostępniamy naszym klientom możliwość wykonywania zrzutów oraz pobrania i wglądu w ich listę w panelu klienta. Zrzuty są wykonywane codziennie o określonej godzinie i przechowywane przez miesiąc.
Aby dane zachowane w zrzucie bazy były spójny (czyli doskonale odzwierciedlał stan bazy z danej chwili), można zastosować jedną z metod:

1. Blokowanie tabel

Blokujemy bazę danych i wstrzymujemy połączenia, które się kumulują. Po zakończeniu zrzutu odblokowujemy bazę i realizujemy kolejkę oczekujących połączeń.

Zalety: Ta metoda wykonywania kopii zapasowej bazy danych jest kompatybilna ze wszystkimi silnikami (w tym MyISAM oraz InnoDB). Zrzut zapewnia integralność danych.

Wady: Podczas operacji wykonywania zrzutu (dump’u), tabele są zablokowane, a co za tym idzie strona WWW jest niedostępna. W większości przypadków nie jest to kłopotliwe i długotrwałe, jednak gdy zrzut wykonuje się dłużej a do bazy jest wiele skolejkowanych połączeń, mogą pojawić się błędy na stronie związane z przekroczeniem liczby jednoczesnych połączeń. W tym wypadku zwiększenie limitu połączeń nie jest dobrym rozwiązaniem, ponieważ zapotrzebowanie występuje jedynie chwilowo, po odblokowaniu tabel. Z drugiej strony, limit połączeń ma chronić serwer przed przeciążeniem, a jego podniesienie mogłoby doprowadzić do stanu wysycenia RAM.

2. Wykorzystanie transakcji

Zalety: Zrzut jest całkowicie transparentny. Baza nie jest blokowana. Integralność danych jest zachowana.

Wady: Ta metoda jest dostępna tylko dla silnika zarządzającego transakcjami (InnoDB). Oznacza to, że nawet jeśli w bazie znajduje się chociaż jedna tabela MyISAM, zrzut będzie niespójny. Co więcej, nawet jeśli w bazie będą tylko tabele InnoDB, a zostanie wykonane polecenie ALTER, CREATE, DROP, RENAME czy TRUNCATE TABLE podczas wykonywania zrzutu, integralność danych zostanie naruszona.

Mając na uwadze wszystkie te aspekty, połączyliśmy obie metody: Jeśli baza danych składa się w 100% z tabel InnoDB, wykorzystujemy transakcje. W innym wypadku, używamy blokowania tabel.

Zalecamy naszym klientom przekonwertowanie wszystkich tabel do formatu InnoDB, który jest aktywny we wszystkich dystrybucjach dostarczanych przez MySQL AB od wersji 4, a od wersji MySQL 5.5.5 jest domyślnym silnikiem (dokumentacja).



Kopie zapasowe w formacie SGBD


Zrzuty baz danych posiadają wiele zalet w porównaniu z ''klasyczną'' kopią zapasową. Metoda ta ma jednak jedną zasadniczą wadę: czas przywracania, który jest zależny od rozmiaru zrzutu.

Wykonując zrzuty i przywracając je codziennie, zebraliśmy mnóstwo danych, dzięki którym postały dokładne statystyki odnośnie czasu trwania eksportów baz danych oraz ich przywracania. Poniżej znajduje się wynik regresji liniowych, które obliczyliśmy dla czasu odpowiedzi ponad 40 000 eksportów baz zawierających jedynie InnoDB (pominęliśmy czas blokowania tabel).

$ ./lr.py list
y=0.142865163057*x1+4.65205077853
R2=0.792955

Czas wykonywania zrzutu w zależności od rozmiaru bazy w MB.

R2 to współczynnik korelacji. Wartość do 0.8 oznacza, że korelacja jest silna i czas wykonania zrzutu bazy jest ściśle powiązany z rozmiarem bazy danych.
Sprawdzaliśmy, czy inne parametry mogą mieć wpływ na czas realizacji zrzutu oraz przywracania. Powtórzyliśmy więc zadanie z kilkoma zmiennymi. Liczba rzędów, średni rozmiar wpisów... Dokładniejsze obliczenie polegały na uwzględnieniu, oprócz liczby wpisów (rzędów), rozmiaru bazy:

$ ./lr.py list
y=2.62412392084*x1+0.130888461045*x2+4.60953501036
R2=0.800904

Czas wykonywania zrzutu w zależności od liczby wpisów (w milionach) i rozmiaru bazy (w MB).

Dzięki tym danym mogliśmy zoptymalizować naszą strategię wykonywania kopii, a tym samym zminimalizować czas przywracania baz w przypadku incydentów. Wiemy, że niedostępna baza oznacza najczęściej niedostępność strony WWW, co jest krytyczne dla naszych klientów. Gdy rozmiar instancji obsługującej bazy danych jest większy niż 4 GB (co odpowiada średniemu czasowi przywracania na poziomie 10 minut), systematycznie duplikujemy zrzuty baz w formacie SGBD. Dzięki temu przywracanie jest dużo szybsze w przypadku problemu na klastrze, gdzie znajdują się bazy. Te dodatkowe kopie zapasowe, które wykonujemy dla instancji większych niż 4 GB, są naszymi wewnętrznymi i nie są udostępniane klientom. Stanowią one dodatkowe zabezpieczenie danych na wypadek awarii. Nasi klienci mają dostęp jedynie do własnych kopii zapasowych.

Do wykonywania kopii zapasowych w formacie SGBD, zarówno dla MySQL jak i MariaDB, używamy narzędzia XtraBackup w trybie full-backup (nie w trybie narastającym), aby usprawnić przywracanie z nich danych. XtraBackup to opensourcowe narzędzie firmy Percona pozwalające na tworzenie spójnych kopii zapasowych, bez potrzeby blokowania tabel bez względu na używany silnik (MyISAM, InnoDB…). XtraBackup tworzy kopie zapasowe na poziomie instancji, a nie bazy danych. W przypadku PostgreSQL korzystamy z narzędzia pg_basebackup.



Sprawdzanie tabel i zapotrzebowanie na RAM


Przed wykonaniem zrzutu (codziennego lub na żądanie) sprawdzamy stan tabel i w razie potrzeby je naprawiamy. W przypadku instancji MySQL i MariaDB używamy do tego polecenia mysqlcheck. Należy podkreślić, że chodzi tu o sporadyczne sytuacje, ponieważ najnowsze wersje MySQL i MariaDB coraz lepiej zarządzają zapisywaniem niespodziewanie przerwanych operacji. W przypadku PostgreSQL, takie sytuacje się nie zdarzają.

Sprawdzanie tabeli i przede wszystkim jej naprawa, może wymagać dużo więcej pamięci RAM, od tej którą dysponuje instancja. W związku z tym, przez cały czas wykonywania polecenia mysqlcheck oraz zrzutu, tymczasowo zwiększamy pamięć RAM instancji, dodając 4 GB. Jeśli bazy danych są wystarczająco duże, użytkownik może zauważyć zwiększenie dostępnej pamięci RAM w statystykach w panelu klienta:







W przypadku, gdy wykonanie zrzutu trwa mniej niż minutę, dodanie pamięci RAM może pozostać niezauważone. W panelu klienta nie będzie to widoczne.

Zwiększenie dostępnej pamięci może naruszyć wykres, przez co krzywa zużycia pamięci będzie prawie nieczytelna. W takiej sytuacji zachęcamy do kliknięcia na «Maximum RAM limit» w dolnej części wykresu, aby widoczny wykres uwzględniał tylko pamięć RAM dostępną standardowo w ramach usługi.



Gdzie przechowujemy kopie zapasowe?


Backup ma sens wyłącznie, gdy jest przechowywany na innej platformie. Zrzuty są więc przechowywane na platformie Public Cloud Storage, która jest całkowicie odizolowana od infrastruktury bazodanowej hostingu WWW. Kopie zapasowe są potrójnie replikowane synchronicznie i rozmieszczone w trzech lokalizacjach (Gravelines, Roubaix, Strasburg). Zrzuty są przechowywane przez miesiąc.

Backupy XtraBackup oraz pg_basebackup dla Prywatnych Serwerów SQL na platformie znajdującej się w Paryżu (hostingi WWW uruchomione przed lipcem 2016) są przechowywane na klastrze Ceph innym niż ten, na którym znajdują się dane produkcyjne. Kopie zapasowe platformy w Gravelines (hostingi WWW uruchomione od lipca 2016) są przechowywane na lokalnych dyskach twardych (a dane produkcyjne na klastrze Ceph).