Wdrożenie zero przestojów - przejściowy schemat Db

14

Osiągnięcie zerowego czasu przestoju dotknęło tego samego problemu, ale potrzebuję porady na temat strategii, którą rozważam.

Kontekst

Aplikacja internetowa z Apache / PHP do przetwarzania po stronie serwera i MySQL DB / system plików do utrwalania.

Obecnie budujemy infrastrukturę. Cały sprzęt sieciowy będzie miał nadmiarowość, a wszystkie kable głównej sieci będą używane w połączonych parach w celu zapewnienia odporności na uszkodzenia. Serwery są konfigurowane jako pary wysokiej dostępności dla sprzętowej odporności na awarie i będą zrównoważone pod względem zarówno odporności na awarie maszyn wirtualnych, jak i ogólnej wydajności.

Moim zamiarem jest, abyśmy byli w stanie zastosować aktualizacje aplikacji bez żadnych przestojów. Bardzo się starałem, projektując infrastrukturę, aby zapewnić 100% czasu sprawności; byłoby bardzo rozczarowujące mieć 10-15 minut przestoju za każdym razem, gdy zastosowano aktualizację. Jest to szczególnie istotne, ponieważ zamierzamy mieć bardzo szybki cykl wydawania (czasami może osiągnąć jedno lub więcej wydań dziennie.

Topologia sieci

To jest podsumowanie sieci:

                      Load Balancer
             |----------------------------|
              /       /         \       \  
             /       /           \       \ 
 | Web Server |  DB Server | Web Server |  DB Server |
 |-------------------------|-------------------------|
 |   Host-1   |   Host-2   |   Host-1   |   Host-2   |
 |-------------------------|-------------------------|
            Node A        \ /        Node B
              |            /            |
              |           / \           |
   |---------------------|   |---------------------|
           Switch 1                  Switch 2

   And onward to VRRP enabled routers and the internet

Uwaga: serwery DB używają replikacji master-master

Sugerowana strategia

Aby to osiągnąć, obecnie myślę o podzieleniu skryptów aktualizacji schematu DB na dwie części. Aktualizacja wyglądałaby następująco:

  1. Serwer WWW w węźle A jest wyłączony; ruch jest nadal przetwarzany przez serwer sieciowy w węźle B.
  2. Zmiany schematu przejściowego są stosowane do serwerów DB
  3. Serwer WWW Baza kodu jest aktualizowana, pamięci podręczne są czyszczone i podejmowane są wszelkie inne działania aktualizacji.
  4. Serwer WWW A zostaje przełączony do trybu online, a serwer B zostaje wyłączony.
  5. Baza kodu serwera WWW B jest aktualizowana, pamięci podręczne są czyszczone i podejmowane są wszelkie inne działania aktualizacji.
  6. Serwer WWW B jest włączony do sieci.
  7. Ostateczne zmiany schematu są stosowane do DB

„Schemat przejściowy” zostałby zaprojektowany w celu ustanowienia bazy danych kompatybilnej z wieloma wersjami. Wykorzystałoby to głównie widoki tabel, które symulują schemat starej wersji, a sama tabela zostałaby zmieniona na nowy schemat. To pozwala starej wersji na normalną interakcję z bazą danych. Nazwy tabel zawierają numery wersji schematu, aby zapewnić, że nie będzie żadnych wątpliwości co do tego, do której tabeli pisać.

„Ostateczny schemat” usunąłby kompatybilność wsteczną i uporządkował schemat.

Pytanie

Krótko mówiąc, czy to zadziała?

dokładniej:

  1. Czy pojawią się problemy z powodu możliwości równoczesnego zapisu w konkretnym punkcie zmiany schematu przejściowego? Czy istnieje sposób, aby upewnić się, że grupa zapytań modyfikujących tabelę i tworzących widok kompatybilny wstecz jest wykonywana kolejno? tzn. z wszelkimi innymi zapytaniami przechowywanymi w buforze, dopóki zmiany schematu nie zostaną zakończone, co zwykle będzie trwało tylko milisekundy.

  2. Czy istnieją prostsze metody, które zapewniają taki stopień stabilności, a jednocześnie umożliwiają aktualizacje bez przestojów? Preferowane jest także unikanie strategii „ewolucyjnej”, ponieważ nie chcę się ograniczać do zgodności ze schematem wstecznym.

Marvin
źródło

Odpowiedzi:

4

Wygląda na to, że to, czego naprawdę szukasz, to nie tyle wysoka dostępność, ile potrzebujesz ciągłej dostępności .

Zasadniczo twój plan będzie działał, ale wydaje się, że zauważyłeś, że główną wadą konfiguracji jest to, że zmiany schematu bazy danych w wydaniu mogą spowodować przestoje lub nieprawidłowe działanie nadal dostępnego węzła. Podejście ciągłej dostępności rozwiązuje ten problem, zasadniczo tworząc szereg środowisk produkcyjnych.

Produkcja pierwsza

To środowisko jest bieżącą wersją oprogramowania używaną przez użytkowników. Ma własne serwery sieciowe, serwery aplikacji oraz serwery baz danych i przestrzeń tabel. Działa niezależnie od jakiegokolwiek innego środowiska. Moduł równoważenia obciążenia, który jest właścicielem punktu końcowego rozpoznawania domen dla tych usług, wskazuje obecnie na te serwery WWW.

Produkcja druga

Jest to zasadniczo środowisko testowe wydania, które jest identyczne z produkcyjnym. Możesz wykonać uaktualnienia wersji tutaj i wykonać testy poczytalności przed wydarzeniem na żywo. Umożliwia to również bezpieczne wykonanie zmian w bazie danych w tym środowisku. Moduł równoważenia obciążenia obecnie nie wskazuje tego środowiska.

Produkcja DR

To kolejny duplikat w oddzielnym centrum danych, które znajduje się w innym regionie świata. Pozwala to na przełączenie awaryjne w przypadku zdarzenia katastroficznego poprzez przełączenie DNS w module równoważenia obciążenia.

Przejdź na żywo

To wydarzenie zasadniczo aktualizuje rekord DNS, aby przejść do produkcji drugiej z produkcji pierwszej lub odwrotnie. Rozprzestrzenianie się po serwerach DNS całego świata zajmuje trochę czasu, więc oba środowiska działają przez chwilę. Niektórzy użytkownicy MOGĄ pracować w istniejących sesjach nad starą wersją oprogramowania. Większość użytkowników będzie nawiązywać nowe sesje w zaktualizowanej wersji oprogramowania.

Migracja danych

Jedyną wadą jest to, że nie wszystkie dane w tym oknie są dostępne dla wszystkich użytkowników w tym czasie. W poprzedniej wersji bazy danych są wyraźnie ważne dane użytkownika, które należy teraz bezpiecznie przenieść do nowego schematu bazy danych. Można to osiągnąć za pomocą dobrze przetestowanego skryptu eksportu i migracji danych lub zadania wsadowego lub podobnego procesu ETL.

Wniosek

Po pełnym zakończeniu wydarzenia związanego z wydaniem, Production Two jest teraz Twoim podstawowym zadaniem i zaczynasz pracę nad instalacją następnej wersji w Production One na następny cykl wdrażania.

Wady

Jest to złożona konfiguracja środowiska i wymaga dużej ilości zasobów systemowych, często dwa do trzech razy więcej niż zasobów systemowych, aby wykonać pomyślnie. Działanie w ten sposób może być kosztowne, szczególnie jeśli masz bardzo duże systemy do intensywnego użytkowania.

wałek klonowy
źródło
Tak więc, jeśli dobrze zrozumiałem, sugerujesz, że zamiast „przejściowej” zmiany schematu DB, która jest stosowana, gdy Db jest nadal w użyciu, Db-A jest utrzymywany online ze starym schematem, podczas gdy Db-B jest aktualizowany do nowej schemat. Gdy aktualizacja jest gotowa do wydania, serwery WWW są zmieniane, a dane, które zostały zapisane w Db A podczas przygotowywania aktualizacji, są migrowane do Db B (prawdopodobnie przez zastosowanie wszystkich zmian po określonym znaczniku czasu).
Marvin
@PeterScott Masz to. Pamiętaj tylko, że nie chcesz uruchamiać skryptu, dopóki nie upewnisz się, że wszystkie aktywne sesje zostały zakończone w starym systemie i minęło wystarczająco dużo czasu, że wszystkie pamięci podręczne DNS zostały zaktualizowane do nowego adresu CNAME lub IP.
wałek klonowy
1
Powinienem być w porządku w obu tych sprawach; sesje są utrwalane w Db zamiast w pamięci serwera, aby uniknąć powiązania sesji z konkretnymi maszynami wirtualnymi, a ja obecnie zamierzam spróbować użyć równoważenia obciążenia opartego na systemie innym niż DNS. Nie będę miał nadmiarowości na poziomie centrum danych, ale może to potrwać około roku po uruchomieniu aplikacji.
Marvin
2

Twoja strategia jest dobra. Chciałbym jedynie rozważyć rozszerzenie „Schematu przejściowego” na pełny zestaw „tabel transakcji”.

W przypadku tabel transakcji SELECT (zapytania) są wykonywane względem znormalizowanych tabel w celu zapewnienia poprawności. Ale wszystkie WSTAWKI, AKTUALIZACJE i USUWANIA bazy danych są zawsze zapisywane w zdenormalizowanych tabelach transakcji.

Następnie osobny, równoległy proces stosuje te zmiany (być może przy użyciu procedur przechowywanych) do znormalizowanych tabel zgodnie z ustalonymi regułami biznesowymi i wymaganiami schematu.

Przez większość czasu byłoby to praktycznie natychmiastowe. Ale rozdzielenie działań pozwala systemowi na uwzględnienie nadmiernej aktywności i opóźnień aktualizacji schematu.

Podczas zmian schematu w bazie danych (B) aktualizacje danych w aktywnej bazie danych (A) trafiałyby do jej tabel transakcji i byłyby natychmiast stosowane do tabel znormalizowanych.

Po przywróceniu bazy danych (B) transakcje z (A) zostaną do niej zastosowane poprzez zapisanie ich w tabelach transakcji (B). Po zakończeniu tej części (A) można obniżyć i zastosować tam zmiany schematu. (B) zakończyłby stosowanie transakcji z punktu (A), jednocześnie obsługując swoje transakcje na żywo, które byłyby w kolejce tak samo jak (A), a „transakcje na żywo” byłyby stosowane w ten sam sposób, gdy wrócił (A).

Wiersz tabeli transakcji może wyglądać podobnie do ...

| ROWID | TRANSNR | DB | TABLE | SQL STATEMENT
    0        0       A    Name   INSERT INTO Name ...
    1        0       A    Addr   INSERT INTO Addr ...
    2        0       A    Phone  INSERT INTO Phone ...
    3        1       A    Stats   UPDATE Stats SET NrOfUsers=...

„Tabele” transakcji mogą faktycznie być wierszami w osobnej bazie danych NoSQL lub nawet sekwencyjnymi plikami, w zależności od wymagań wydajnościowych. Dodatkową zaletą jest to, że kodowanie aplikacji (w tym przypadku strony internetowej) jest nieco prostsze, ponieważ zapisuje tylko w tabelach transakcji.

Pomysł opiera się na tych samych zasadach co księgowość podwójnego zapisu i z podobnych powodów.

Tabele transakcji są analogiczne do „dziennika” księgowości. W pełni znormalizowane tabele są analogiczne do „księgi rachunkowej”, przy czym każda tabela jest nieco podobna do „konta” księgowego.

W księgowości każda transakcja otrzymuje dwa wpisy do dziennika. Jeden dla „księgowego” konta księgowego, a drugi dla „uznanego” konta.

W RDBMS „dziennik” (tabela transakcji) otrzymuje wpis dla każdej znormalizowanej tabeli, która ma zostać zmieniona przez tę transakcję.

Kolumna DB na powyższej ilustracji tabeli wskazuje, z której bazy danych pochodzi transakcja, umożliwiając w ten sposób odfiltrowanie wierszy z drugiej bazy danych w kolejce i ponowne ich zastosowanie po przywróceniu drugiej bazy danych.

DocSalvager
źródło
1
Podoba mi się porównanie do księgowości. Tak więc, o ile rozumiem, tabele transakcji pozwalają mi na bardzo małe opóźnienie w zapisywaniu danych do określonej znormalizowanej tabeli, dzięki czemu mogę zastosować wszystkie zmiany schematu bez ryzyka przerwania w połowie zmian? Następnie, przy aktualnym schemacie tabeli, mogę wznowić proces, który stosuje znormalizowane transakcje do znormalizowanych tabel (proces ten może mapować stare zapytania danych schematu na nowy schemat)?
Marvin
1
Tak. Zmodyfikowałbyś mapowane procedury przechowywane (lub cokolwiek innego), aby uwzględnić zarówno stare, jak i nowe dane. Nowe kolumny NOT-NULL mogą być wypełnione ze starych danych kodem, który oznacza „monit o to przy aktualizacji użytkownika”. Kolumny do podzielenia (tj. FULLNAME na FIRST i LAST) będą wymagały pewnego algorytmu. Polecam dodanie do tabel co najmniej 1 kolumny „podobnej do komentarza”, aby poznać nowe wymagania dotyczące biz. Jeśli tego nie zrobisz, gwarantuję, że użytkownicy dopasują inne kolumny do tego celu, a poprawienie danych będzie prawie niemożliwe.
DocSalvager,
W jaki sposób można zapobiec stosowaniu zapytań SELECT dla starego schematu w nowym schemacie? Mógłbym użyć utworzyć widok tabeli i zmienić nazwę tabeli schematu (z numerem wersji schematu), ale nadal byłoby to problematyczne podczas wprowadzania zmian schematu, ponieważ dotyczą one bezpośrednio tabeli znormalizowanej.
Marvin
1
Kiedy dodajesz tabelę, kolumnę lub cokolwiek innego do RDBMS, w rzeczywistości dodajesz wiersze do zestawu tabel wewnętrznych, do których można zapisać tylko silnik RDBMS. DBA zarządzają bazą danych, odpytując je za pośrednictwem WIDOKÓW. Ponieważ Oracle, IBM, MS itp. Są ekspertami i twierdzą, że to najlepszy sposób, wydaje się, że powinniśmy podążać za nimi. Utwórz zestaw WIDOKÓW dla każdej wersji aplikacji. Możesz modelować je na podstawie (zwykle dość zdormalizowanych) tabel, które programiści chcą, abyś utworzył, dzięki czemu możesz odpowiednio normalizować, aby zapobiec uszkodzeniu danych.
DocSalvager,
Dzięki. Muszę o tym pomyśleć. buduję warstwę ORM w aplikacji, która całkowicie usuwa całą logikę utrzymywania stanu z głównej domeny; opierając się bardziej na programowaniu po stronie serwera, rozwiązuję problemy bardziej z tej strony niż ze strony administracyjnej DB. Stosując moją obecną strategię, Db byłby całkiem płaski z ORM aktywnie zarządzającym surowymi tabelami. Dodanie widoków tabeli i ewentualnie dziennika transakcji zwiększa złożoność ORM, ale zapewnia także obsługę wielu wersji schematu bez rozszczepiania danych.
Marvin