IMO, podczas aktualizacji głównych wersji, powinien istnieć odpowiedni plan awaryjny, ponieważ na wypadek, gdyby aplikacja okazała się błędna lub nie działała dobrze na zaktualizowanej wersji, powinniśmy być w stanie natychmiast przywrócić starszą wersję. Slony-I zapewnia taką funkcjonalność na zasadzie switchbacku. Ten post pokazuje, minimalne przestoje, w tym etapy przełączania/przełączania.
Przed przejściem do wersji demonstracyjnej należy zwrócić uwagę na jeden ważny krok, wcześniej do wersji PG 9.0.x kolumny bajtowe typu danych służą do przechowywania danych w formacie ESCAPE, a nowsze wersje w formacie HEX. Podczas przełączania wstecz (z nowszej wersji do starszej wersji) tego rodzaju różnice w formacie bajtów nie są obsługiwane przez Slony-I, dlatego format ESCAPE powinien być utrzymywany przez cały czas trwania aktualizacji, w przeciwnym razie może wystąpić błąd:
ERROR remoteWorkerThread_1_1: error at end of COPY IN: ERROR: invalid input syntax for type bytea
CONTEXT: COPY sl_log_1, line 1: "1 991380 1 100001 public foo I 0 {id,500003,name,"A ",b,"\\x41"}"
ERROR remoteWorkerThread_1: SYNC aborted
Aby to naprawić, żadne zmiany nie są wymagane w PG 8.4.x, ale w PG 9.3.5 parametr bytea_output powinien być ustawiony z HEX na ESCAPE, jak pokazano. Możemy ustawić go na poziomie klastra ($PGDATA/postgresql.conf) lub na poziomie użytkownika (ALTER TABLE…SET), wolałem przejść ze zmianami na poziomie użytkownika.
slavedb=# alter user postgres set bytea_output to escape;
ALTER ROLE
Przejdźmy do kroków aktualizacji. Poniżej znajdują się moje dwie wersje danych serwera używane w tym demo, zmień je odpowiednio zgodnie z konfiguracją serwera, jeśli próbujesz:
Origin Node (Master/Primary are called as Origin) Subscriber Node (Slave/Secondary are called as Subscriber)
------------------------------------------------- ----------------------------------------------------------
Host IP : 192.168.22.130 192.168.22.131
OS Version : RHEL 6.5 64 bit RHEL 6.5 64 bit
PG Version : 8.4.22 (5432 Port) 9.3.5 (5432 Port)
Slony Vers. : 2.2.2 2.2.2
PG Binaries : /usr/local/pg84/bin /opt/PostgreSQL/9.3/
Database : masterdb slavedb
PK Table : foo(id int primary key, name char(20), image bytea) ...restore PK tables structure from Origin...
Dla łatwego zrozumienia i łatwej implementacji podzieliłem demo na trzy sekcje
1. Kompilacja plików binarnych Slony-I z wersjami PostgreSQL2. Tworzenie i wykonywanie skryptów replikacji
3. Testowanie przełączania/przełączania powrotnego.
1. Kompilacja dla binariów Slony-I z wersją PostgreSQL
Pobierz źródła Slony-I stąd i wykonaj instalację źródeł na plikach binarnych PostgreSQL w węzłach Origin i subskrybent.
On Origin Node:
# tar -xvf slony1-2.2.2.tar.bz2
# cd slony1-2.2.2
./configure --with-pgbindir=/usr/local/pg84/bin
--with-pglibdir=/usr/local/pg84/lib
--with-pgincludedir=/usr/local/pg84/include
--with-pgpkglibdir=/usr/local/pg84/lib/postgresql
--with-pgincludeserverdir=/usr/local/pg84/include/postgresql/
make
make install
On Subscriber Node: (assuming PG 9.3.5 installed)
# tar -xvf slony1-2.2.2.tar.bz2
# cd slony1-2.2.2
./configure --with-pgconfigdir=/opt/PostgreSQL/9.3/bin
--with-pgbindir=/opt/PostgreSQL/9.3/bin
--with-pglibdir=/opt/PostgreSQL/9.3/lib
--with-pgincludedir=/opt/PostgreSQL/9.3/include
--with-pgpkglibdir=/opt/PostgreSQL/9.3/lib/postgresql
--with-pgincludeserverdir=/opt/PostgreSQL/9.3/include/postgresql/server/
--with-pgsharedir=/opt/PostgreSQL/9.3/share
make
make install
2. Tworzenie skryptów replikacji i wykonywanie
Aby skonfigurować replikację, musimy utworzyć kilka skryptów, które zajmą się replikacją, w tym przełączeniem/przełączaniem wstecznym.
1. initialize.slonik – ten skrypt przechowuje informacje o połączeniu węzłów pochodzenia/subskrybenta.
2. create_set.slonik — ten skrypt przechowuje wszystkie tabele Origin PK replikujące się do węzła subskrybenta.
3. subscribe_set.slonik — ten skrypt rozpoczyna replikację zestawów danych do węzła subskrybenta.
4. switchover.slonik – ten skrypt pomaga przenieść kontrolę z Origin na subskrybenta.
5. switchback.slonik – ten skrypt pomaga przywrócić kontrolę z subskrybenta do Origin.
Na koniec dwa kolejne skrypty startowe “start_OriginNode.sh” i „start_SubscriberNode.sh” który uruchamia procesy slon zgodnie z plikami binarnymi skompilowanymi na węzłach początkowych/abonenckich.
Pobierz wszystkie skrypty stąd.
Oto przykładowe dane w Origin Node(8.4.22) w Foo Table z kolumną typu danych bajtów, które zreplikujemy do Subscriber Node (9.3.5) za pomocą utworzonych skryptów.
masterdb=# select * from foo;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
(3 rows)
Wywołajmy skrypty jeden po drugim, aby skonfigurować replikację. PAMIĘTAJ, ŻE WSZYSTKIE SKRYPT SLONIK POWINNY BYĆ WYKONYWANE TYLKO W WĘZLE POCHODZENIA, Z WYJĄTKIEM „start_OriginNode.sh” I „start_SubscriberNode.sh”, KTÓRE POWINNY BYĆ WYKONYWANE INDYWIDUALNIE.
-bash-4.1$ slonik initalize.slonik
-bash-4.1$ slonik create_set.slonik
create_set.slonik:13: Set 1 ...created
create_set.slonik:16: PKey table *** public.foo *** added.
-bash-4.1$ sh start_OriginNode.sh
-bash-4.1$ sh start_SubscriberNode.sh //ON SUBSCRIBER NODE
-bash-4.1$ slonik subscribe_set.slonik
Po pomyślnym wykonaniu powyższego skryptu można zauważyć, że dane w Origin(masterdb) zostały zreplikowane do subskrybenta (slavedb). Nie zezwala również na żadne operacje DML w węźle subskrybenta:
slavedb=# select * from foo;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
(3 rows)
slavedb=# insert into foo values (4,'PG-Experts','Image2');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0
Fajnie… Przenieśliśmy dane do nowszej wersji PostgreSQL 9.3.5. Na tym etapie, jeśli uważasz, że wszystkie dane zostały zreplikowane do węzła subskrybenta, możesz dokonać przełączenia.
3. Testowanie przełączania/powrotu.
Przejdźmy do najnowszej wersji ze skryptem i spróbujmy wstawić dane na węzłach subskrybenta/początku.
-bash-4.1$ slonik switchover.slonik
switchover.slonik:8: Set 1 has been moved from Node 1 to Node 2
slavedb=# insert into foo values (4,'PG-Experts','Image2');
INSERT 0 1
masterdb=# select * from foo ;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
4 | PG-Experts | Image2
(4 rows)
masterdb=# insert into foo values (5,'PG-Experts','Image3');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0
Idealnie… To jest to, czego szukamy, teraz slavedb (węzeł subskrybenta) działający w wersji PG 9.3.5 akceptujący dane i masterdb (węzeł źródłowy) odbierający dane slavedb. Również jego odrzucanie DMLs wykonywane na masterdb.
Slony-I Logs pokazuje ruchy identyfikatora węzła źródłowego/abonenta w momencie przełączenia:
2014-12-12 04:55:06 PST CONFIG moveSet: set_id=1 old_origin=1 new_origin=2
2014-12-12 04:55:06 PST CONFIG storeListen: li_origin=1 li_receiver=2 li_provider=1
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: update provider configuration
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: helper thread for provider 1 terminated
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: disconnecting from data provider 1
...
...
2014-12-12 04:55:11 PST INFO start processing ACCEPT_SET
2014-12-12 04:55:11 PST INFO ACCEPT: set=1
2014-12-12 04:55:11 PST INFO ACCEPT: old origin=1
2014-12-12 04:55:11 PST INFO ACCEPT: new origin=2
2014-12-12 04:55:11 PST INFO ACCEPT: move set seq=5000006393
2014-12-12 04:55:11 PST INFO got parms ACCEPT_SET
Jeśli na tym etapie napotkasz jakiekolwiek problemy, możesz wrócić do starszej wersji. Po przełączeniu możesz kontynuować korzystanie ze starszej wersji, dopóki Twoja aplikacja lub inne problemy nie zostaną rozwiązane. Jest to idealny plan wycofywania bez marnowania czasu w przypadku problemów po przełączeniu.
-bash-4.1$ slonik switchback.slonik
switchback.slonik:8: Set 1 has been moved from Node 2 to Node 1
slavedb=# insert into foo values (5,'PG-Experts','Image3');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0
masterdb=# insert into foo values (5,'PG-Experts','Image3');
INSERT 0 1
slavedb=# select * from foo ;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
4 | PG-Experts | Image2
5 | PG-Experts | Image3
(5 rows)
Bardzo dobrze…!!! Czy to nie jest dokładne wycofanie z minimalnym przestojem? Tak, to idealne przełączanie między węzłami bez utraty transakcji.
Dzienniki pokazujące przejście od subskrybenta do węzła pochodzenia:
2014-12-12 04:58:45 PST CONFIG moveSet: set_id=1 old_origin=2 new_origin=1
2014-12-12 04:58:45 PST CONFIG storeListen: li_origin=2 li_receiver=1 li_provider=2
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: update provider configuration
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: helper thread for provider 2 terminated
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: disconnecting from data provider 2
2014-12-12 04:58:46 PST CONFIG storeListen: li_origin=2 li_receiver=1 li_provider=2
...
...
2014-12-12 04:58:47 PST INFO start processing ACCEPT_SET
2014-12-12 04:58:47 PST INFO ACCEPT: set=1
2014-12-12 04:58:47 PST INFO ACCEPT: old origin=2
2014-12-12 04:58:47 PST INFO ACCEPT: new origin=1
2014-12-12 04:58:47 PST INFO ACCEPT: move set seq=5000006403
2014-12-12 04:58:47 PST INFO got parms ACCEPT_SET
2014-12-12 04:58:48 PST CONFIG moveSet: set_id=1 old_origin=2 new_origin=1
W tym czasie mogłeś zauważyć, że żadna z transakcji nie zostanie utracona podczas operacji przełączania między wersjami PostgreSQL. Tylko przestój może być twoją aplikacją do uruchomienia/zatrzymania w celu połączenia z węzłami Origin i abonentami, ale podczas gdy węzły Origin/Subskrybent nigdy nie są wyłączane, są po prostu uruchomione.
Pamiętaj, że pokazana tutaj metoda jest przydatna nie tylko w przypadku aktualizacji, ale jest to ta sama metoda w Slony-I do poruszania się między węzłami.
Dziękuję za Twoją cierpliwość :). Mam nadzieję, że ten post pomoże ci zaktualizować PostgreSQL przy minimalnym przestoju przy użyciu Slony-I, w tym odpowiedniego planu wycofania.