PITR jednego tenanta: odtworzenie jednej bazy
- data
- kategoria
- Reliability Engineering
- także w
- Databases · Incident Management
- czytanie
- 2 min / 340 słów
Najprostszy przykład PITR pojedynczej bazy to system multi-tenant, w którym każdy tenant ma własną bazę.
tenant_acme
tenant_globex
tenant_initech
O 10:43 błędny job zepsuł dane tylko w tenant_acme.
Pozostali tenantci działają poprawnie.
Nie ma sensu cofać całego serwera.
Chcemy cofnąć tylko jedną bazę:
tenant_acme -> stan z 10:42
Cel operacji
Operacja ma być mała i konkretna.
odtworzyć kopię serwera do 10:42
wziąć z niej bazę tenant_acme
podmienić produkcyjną bazę tego tenanta
wznowić ruch tenanta
To nie jest pełny disaster recovery.
To jest recovery jednego klienta.
1. Zamrożenie tenanta
Najpierw zatrzymujemy zapisy tylko dla tenant_acme.
ustaw tenant_acme w maintenance mode
zatrzymaj workery tenant_acme
zostaw pozostałych tenantów online
Chodzi o to, żeby uszkodzona baza nie przyjmowała nowych zapisów podczas recovery.
Jeżeli tego nie zrobimy, będziemy odtwarzać stan z przeszłości, a równolegle produkcja będzie dopisywać nowe dane do starej bazy.
2. Restore obok
Nie odtwarzamy od razu na produkcji.
Stawiamy instancję pomocniczą z backupu i WAL do wybranego czasu.
target time: 10:42
Po restore mamy pomocniczy serwer ze stanem sprzed błędu.
Na nim sprawdzamy, czy baza tenant_acme wygląda dobrze.
czy błędne dane zniknęły
czy aplikacja umie czytać bazę
czy podstawowe zapytania działają
3. Dump jednej bazy
Z pomocniczego serwera bierzemy tylko bazę uszkodzonego tenanta.
pg_dump -Fc tenant_acme > tenant_acme_1042.dump
Nie interesują nas bazy innych tenantów.
Nie przenosimy całego serwera.
Wyciągamy tylko ten fragment, który chcemy przywrócić.
4. Import jako nowa baza
W produkcji tworzymy nową bazę, na przykład:
tenant_acme_restored
I importujemy dump:
createdb tenant_acme_restored
pg_restore -d tenant_acme_restored tenant_acme_1042.dump
Stara baza tenant_acme nadal istnieje.
To ważne, bo można jeszcze porównać dane albo wrócić do niej, jeśli restore okaże się zły.
5. Przełączenie tenanta
Aplikacja musi wiedzieć, że tenant_acme ma teraz używać nowej bazy.
W najprostszym modelu mamy tabelę albo konfigurację:
tenant: acme
database: tenant_acme
Zmieniamy ją na:
tenant: acme
database: tenant_acme_restored
Potem restartujemy albo odświeżamy procesy, które trzymają stare połączenia.
API
workery
joby cykliczne
6. Sprawdzenie
Po przełączeniu robimy krótki sanity check.
tenant_acme loguje się poprawnie
podstawowy odczyt działa
podstawowy zapis działa
workery piszą do nowej bazy
metryki nie pokazują błędów
Jeżeli wszystko wygląda dobrze, wyłączamy maintenance mode dla tenant_acme.
Starej bazy nie kasujemy od razu.
Zostaje jako materiał do porównania i postmortem.
Co z danymi po 10:42
Jeżeli tenant był zamrożony dopiero o 11:15, wszystko zapisane między 10:42 a 11:15 nie pojawi się w odtworzonej bazie.
To jest koszt tej operacji.
Trzeba go nazwać wprost:
co tracimy
co da się przepisać ręcznie
co da się odtworzyć z logów
co trzeba zakomunikować klientowi
PITR nie jest cofaniem czasu bez konsekwencji.
Jest wyborem punktu, do którego wracamy.
Minimalna procedura
Całość można sprowadzić do krótkiej checklisty.
potwierdź, że problem dotyczy tylko tenant_acme
zamroź tenant_acme
odtwórz serwer pomocniczy do 10:42
zrób dump bazy tenant_acme
zaimportuj dump jako tenant_acme_restored
przełącz tenant_acme na nową bazę
sprawdź odczyt, zapis i workery
odmroź tenant_acme
zostaw starą bazę do analizy
To jest sens PITR pojedynczej bazy w tym przykładzie.
Nie ratujemy całej platformy.
Nie dotykamy innych tenantów.
Odtwarzamy jedną bazę, bo granica problemu jest jasna.