Natív PostgreSQL replikáció

A Unix/Linux szerverek üzemeltetése wikiből
(Változatok közti eltérés)
(Streaming szinkron replikáció konfigurálása)
44. sor: 44. sor:
 
A kaszkádosított replikáció egy kicsit kilóg a sorból abban az értelemben, hogy ez inkább replikációs terheléselosztásnak tekinthető. A PostgreSQL 9.2-es verziójától kezdődően használhatjuk, a segítségével nem kell az összes slave-nek a masterről replikálnia, az mintegy "hullám" végighaladhat a rendszerünkön. Képzeljünk el egy olyan esetet, amikor van van masterünk, mellette egy szinkron slave és az összes többi slave a szinkron slave-ről replikál. Ezzel a mastert jelentősen tehermentesítettük. Érezzük, hogy ez a feature főleg nagy clusterek építésekor hasznos.
 
A kaszkádosított replikáció egy kicsit kilóg a sorból abban az értelemben, hogy ez inkább replikációs terheléselosztásnak tekinthető. A PostgreSQL 9.2-es verziójától kezdődően használhatjuk, a segítségével nem kell az összes slave-nek a masterről replikálnia, az mintegy "hullám" végighaladhat a rendszerünkön. Képzeljünk el egy olyan esetet, amikor van van masterünk, mellette egy szinkron slave és az összes többi slave a szinkron slave-ről replikál. Ezzel a mastert jelentősen tehermentesítettük. Érezzük, hogy ez a feature főleg nagy clusterek építésekor hasznos.
   
== Streaming szinkron replikáció konfigurálása ==
+
== Streaming aszinkron replikáció konfigurálása ==
 
Először is fel kell telepítenünk mindkét gépünkön a PostgreSQL-t:
 
Először is fel kell telepítenünk mindkét gépünkön a PostgreSQL-t:
 
<pre>
 
<pre>
74. sor: 74. sor:
 
wal_level = hot_standby # engedélyezi a read-only lekérdezéseket a host standby rendszeren
 
wal_level = hot_standby # engedélyezi a read-only lekérdezéseket a host standby rendszeren
 
max_wal_senders = 5 # egyszerre max. ennyi standby szerver kapcsolódhat a masterre
 
max_wal_senders = 5 # egyszerre max. ennyi standby szerver kapcsolódhat a masterre
wal_keep_segments = 16 # ennyi WAL szegmenst fog megőrizni a master a pg_xlog könyvtárban. Erre azért van szükség, hogy az online backup és a streaming replikáció megkezdése között nehogy törölje a master ezeket a fájlokat. A WAL szegmensek általában 16 MB méretűek.
+
wal_keep_segments = 16 # ennyi WAL szegmenst fog megőrizni a master a pg_xlog könyvtárban. \\
  +
Erre azért van szükség, hogy az online backup és a streaming replikáció megkezdése között \\
  +
nehogy törölje a master ezeket a fájlokat. A WAL szegmensek általában 16 MB méretűek.
  +
# %f jelenti a fájlnevet, a %p pedig a path-t
  +
archive_command = 'cp -i %p /var/lib/postgresql/9.1/main/pg_xlog/%f' # fontos, hogy a pg_xlog \\
  +
könyvtárat használjuk, mert ide kerülnek a WAL szegmensek
  +
archive_mode = on
 
</pre>
 
</pre>
 
Ezután indítsuk el a masteren a portgrest és készítsünk róla egy backupot, amit átmásolunk a slave-re:
 
Ezután indítsuk el a masteren a portgrest és készítsünk róla egy backupot, amit átmásolunk a slave-re:
 
<pre>
 
<pre>
 
su - postgres
 
su - postgres
  +
# az rsync miatt érdemes eljátszani a szervereink postgres felhasználói \\
  +
között az SSH kulcscserét. Akár egy scriptet is írhatunk a célra, megéri.
 
psql -c "SELECT pg_start_backup('label', true)"
 
psql -c "SELECT pg_start_backup('label', true)"
exit
 
 
cd /var/lib/postgresql/9.1/main
 
cd /var/lib/postgresql/9.1/main
rsync -ave ssh /var/lib/postgresql/9.1/main/ 172.16.0.2:/var/lib/postgresql/9.1/main --exclude backup_label --exclude postmaster.opts --exclude server.crt --exclude server.key --exclude PG_VERSION --exclude postmaster.pid
+
rsync -ave ssh /var/lib/postgresql/9.1/main/ 172.16.0.2:/var/lib/postgresql/9.1/main \\
su - postgres
+
--exclude postmaster.opts --exclude server.crt --exclude server.key --exclude postmaster.pid
 
psql -c "SELECT pg_stop_backup()"
 
psql -c "SELECT pg_stop_backup()"
exit
 
 
</pre>
 
</pre>
Most térjünk vissza a slave szerverhez. A ph_hba.conf-hoz adjuk hozzá az alábbi sort:
+
Most térjünk vissza a slave szerverhez. A pg_hba.conf-hoz adjuk hozzá az alábbi sort:
 
<pre>
 
<pre>
 
host replication replicator 172.16.0.2/32 md5
 
host replication replicator 172.16.0.2/32 md5
99. sor: 99. sor:
 
hot_standby = on
 
hot_standby = on
 
</pre>
 
</pre>
  +
Létre kell hoznunk egy recovery.conf állomány a $PGDATA alatt. Ez debian alaptelepítés esetén a /var/lib/postgresql/9.1/main.
  +
A recovery.conf tartalma legyen ez:
  +
<pre>
  +
# streaming replikációnál mindig on
  +
standby_mode = 'on'
   
  +
primary_conninfo = 'host=172.16.0.1 port=5432 user=replicator password=vasbeton application_name=dbtest2'
  +
  +
  +
# ez indítja a failovert
  +
trigger_file = '/tmp/pgsql.trigger'
  +
  +
# a masteren lévő archive_command párja:
  +
restore_command = 'cp -i /var/lib/postgresql/9.1/main/pg_xlog/%f %p'
  +
</pre>
  +
Ha ezzel megvagyunk, a munka "aszinkron" része már készen is van. Indítsuk újra az adatbázisainkat, és nézzük meg az alábbi lekérdezést a masteren:
  +
<pre>
  +
postgres=# select application_name, state, sent_location, write_location, sync_state from pg_stat_replication ;
  +
application_name | state | sent_location | write_location | sync_state
  +
------------------+-----------+---------------+----------------+------------
  +
walreceiver | streaming | 0/8001650 | 0/8001650 | async
  +
(1 row)
  +
</pre>
  +
Láthatjuk, hogy a streaming aszinkron replikáció működik. Érdemes lehet megnézni a wal sender folyamatot a masteren:
  +
<pre>
  +
root@dbtest1:~# ps ax | grep wal
  +
1442 ? Ss 0:00 postgres: wal writer process
  +
1460 ? Ss 0:00 postgres: wal sender process replicator 172.16.0.2(53859) streaming 0/8001650
  +
</pre>
  +
A slave-en a WAL receiver processt figyelhetjük meg:
  +
<pre>
  +
root@dbtest2:~# ps ax | grep wal
  +
1329 ? Ss 0:00 postgres: wal receiver process streaming 0/8001650
  +
</pre>
  +
  +
== Streaming szinkron replikáció konfigurálása ==
  +
A szinkron replikáció beállítása az aszinkronéra épül, így először a fenti pont szerinti lépéseket kell végrehajtani. Ha ez kész, már szinte célbaértünk, hiszen csak egy-egy paramétert kell módosítani a masteren és a slave-en. Lássuk ezeket!
  +
A masteren a synchronous_standby_names paramétert kell beállítanunk a szinkron standby szerverünk nevére. Nem kell megegyeznie az FQDN-ével, látni fogjuk hogy a túloldalon is meg kell adnunk ezt a nevet. Az is megkötés, hogy egyszerre csak egy szinkron standby szerver kapcsolódhat a masterre.
  +
<pre>
  +
synchronous_standby_names = 'dbtest2'
  +
</pre>
  +
A slave oldalán szintén nagyon egyszerű a helyzet, a recovery.conf primary_connfinfo paraméterét kell bővítenünk egy application_name opcióval:
  +
<pre>
  +
# aszinkron esetben:
  +
#primary_conninfo = 'host=172.16.0.1 port=5432 user=replicator password=vasbeton'
  +
# szinkron esetben
  +
primary_conninfo = 'host=172.16.0.1 port=5432 user=replicator password=vasbeton application_name=dbtest2'
  +
<pre>
  +
  +
Meg is volnánk :) Nézzük meg a masteren a pg_stat_replication view tartalmát, változott-e:
  +
<pre>
  +
postgres=# select application_name, state, sent_location, write_location, sync_state from pg_stat_replication;
  +
application_name | state | sent_location | write_location | sync_state
  +
------------------+-----------+---------------+----------------+------------
  +
dbtest2 | streaming | 0/80016A8 | 0/80016A8 | sync
  +
(1 row)
  +
</pre>
  +
Érdekes tartalma van a lognak (/var/log/postgresql/postgresql-9.1-main.log) is (felül a frissebb bejegyzések):
  +
<pre>
  +
2012-12-10 23:58:58 CET LOG: standby "dbtest2" is now the synchronous standby with priority 1
  +
2012-12-10 23:58:53 CET LOG: incomplete startup packet
  +
2012-12-10 23:58:53 CET LOG: database system is ready to accept connections
  +
2012-12-10 23:58:53 CET LOG: autovacuum launcher started
  +
2012-12-10 23:58:53 CET LOG: database system was shut down at 2012-12-10 23:58:28 CET
  +
</pre>
  +
Az incomplete startup packet rémisztő lehet, de azt a replikáló szerver okozza.
  +
A slave szerveren is érdemes szétnézni:
  +
<pre>
  +
2012-12-10 23:58:58 CET LOG: streaming replication successfully connected to primary
  +
2012-12-10 23:58:58 CET LOG: database system is ready to accept read only connections
  +
2012-12-10 23:58:58 CET LOG: consistent recovery state reached at 0/8001650
  +
</pre>
 
== Magas rendelkezésre állás virtuális IP-vel ==
 
== Magas rendelkezésre állás virtuális IP-vel ==
  +
A nagyobb rendszereket üzemeltetők gyakran elgondolkodnak azon, hogyan tehetnék még megbízhatóbbá rendszerüket: mit tegyenek, egy szerver kiesése esetén, esetleg tudják-e ezt a cselekvést automatizálni. A következő bekezdés egy ilyen módszert ragad ki a sok megoldás közül.
 
=== Mi az a virtuális IP cím? ===
 
=== Mi az a virtuális IP cím? ===
  +
A virtuális IP cím (röviden VIP) egy olyan IP cím, ami nem kimondottan egy szerverhez vagy egy hálózati kártyához van rendelve, hanem több alkalmazás, szerver osztozik rajta. Ha egyidejűleg csak egyetlen géphez rendeljük hozzá, majd a gép kiesése esetén egy másik géphez ami képes átvenni a funkcióját, lényegében egy VIP alapú failover megoldást kapunk.
 
=== Hogyan tudom konfigurálni? ===
 
=== Hogyan tudom konfigurálni? ===
  +
A VIP automatikus kezeléséhez a keepalived programot fogom használni. A keepalived egy "útválasztó" program, amivel terheléelosztást (loadbalancing) és magas rendelkezésreállást (High Availability - HA) tudunk megvalósítani. Egy adatbázis esetében a terheléselosztás nem olyan egyszerű feladat, mint egy webszerver esetében, ezért erre más megoldásokat szoktak használni (pl. pgpool). Itt én csak a HA rész beállítását fogom bemutatni.
 
=== Automatikus failover ===
 
=== Automatikus failover ===
  +
A keepalived telepítéséhez futtassuk az alábbi parancsot a masteren és a slave-en egyaránt:
  +
<pre>
  +
apt-get install keepalived
  +
</pre>
  +
A /etc/keepalived alatt fogja keresni a keepalived.conf-ot, amit nekünk kell létrehoznunk.
  +
A master esetében a fájl tartalma legyen ez:
  +
<pre>
  +
vrrp_instance VI_1 {
  +
# kezdeti állapot
  +
state MASTER
  +
interface eth0
  +
  +
# egy NIC-et több vrrpd is használhat, ezzel lehet őket
  +
# megkülönböztetni
  +
virtual_router_id 1
  +
  +
# master választáskor a minél magasabb prioritással lehetünk masterek
  +
# a dokumentáció szerint ha egy szervert nagyon szeretnénk masternek,
  +
# akkor a prioritása legyen 50-el magasabb mint a többié
  +
priority 100
  +
  +
# ezt a paramétert itt is meg kell adni, hogy a "feltámadása" esetén
  +
# ne vegye el a VIP-et a slave-től
  +
nopreempt
  +
  +
# VIP
  +
virtual_ipaddress {
  +
192.168.100.100/24 dev eth0 label eth0:vip
  +
}
  +
}
  +
</pre>
  +
A slave esetén a keepalived.conf tartalma:
  +
<pre>
  +
vrrp_instance VI_1 {
  +
# kezdeti állapot
  +
state BACKUP
  +
interface eth0
  +
  +
# ha a slave megkapta a VIP-et és a master feléled, akkor is
  +
# megtartja a VIP-et
  +
nopreempt
  +
  +
# egy NIC-et több vrrpd is használhat, ezzel lehet őket
  +
# megkülönböztetni
  +
virtual_router_id 1
  +
  +
# master választáskor a minél magasabb prioritással lehetünk masterek
  +
# a dokumentáció szerint ha egy szervert nagyon szeretnénk masternek,
  +
# akkor a prioritása legyen 50-el magasabb mint a többié
  +
priority 50
  +
  +
# VIP
  +
virtual_ipaddress {
  +
192.168.100.100/24 dev eth0 label eth0:vip
  +
}
  +
  +
# slave -> master átmenet
  +
notify_master "/etc/keepalived/to_master.sh"
  +
}
  +
</pre>
  +
  +
A to_master.sh pedig így néz ki:
  +
<pre>
  +
#!/bin/bash
  +
  +
# létrehozza a triggerfájlt -> a slave masterre vált és írhatóvá válik
  +
touch /tmp/pgsql.trigger
  +
</pre>
  +
   
 
== Teljesítménytesztek ==
 
== Teljesítménytesztek ==

A lap 2012. december 11., 18:42-kori változata

Tartalomjegyzék

1 Bevezetés

A PostgreSQL 9.0-ás verziójától kezdve támogatja a natív replikációt, ami talán ez az egyik legjobban várt funkciója hosszú idők óta. Eddig is léteztek más replikációs megoldások (PgPool II, Slony, stb.), amelyek akár többlet funkcionalitással is rendelkezhettek (load balancing), mégsem jelentenek igazi megoldást a problémáinkra. A jelen szócikk ezen témakörbe nyújt egy kis betekintést.

A replikáció konfigurálásához két debian Linux operációs rendszert használok csomagból telepített PostgreSQL 9.1 verziókkal. Az alaprendszer squeeze, ehhez a szükséges binárisokat a wheezy tárolóiból töltöttem le (csak hozzá kell adni a tárolók a sources.list-hez). A két szerver közvetlenül is össze lesz kötve egymással (172.16.0.0/24-es hálózat), ez a failover szempontjából fontos. Több szerver esetén a közvetlen összeköttetések nagyon megbonyolítanák a beállításokat, akkor célszerűbb switch-eken keresztül összekapcsolni a rendszereket.

Teszthalo.png

2 Követelmények

2.1 Replikáció követelményei

A replikációnak több követelménye van, ami nem csak az PostgreSQL verziószámára terjed ki:

  • a replikációban részt vevő operációs rendszereknek azonos architektúrájúnak kell lennie
  • legalább PostgreSQL 9.0

Azonos architektúrának számít, ha mind amd64, x386 stb. Látszik hogy nem szabad keverni 32 és 64 bites rendszereket, csak tisztán az egyiket, ill. tisztán a másikat használhatjuk. Törekedni kell a PostgreSQL-t is azonos verzión tartani. Ha frissítjük, célszerű először a slave rendszerrel kezdeni, mert valószínűbb, hogy egy új rendszer képes feldolgozni egy régebbi üzeneteit, mint fordítva.

2.2 Failover követelményei

  • közvetlen kapcsolat a két szerver között
  • egy virtuális IP cím

A fent ismertetett felállás szerint a két szerver közvetlen kapcsolatban kell álljon egymással. Ez azért jó, mert a kapcsolat csak a két oldaltól függ, vagyis nagyon stabilnak tekinthető. Ha egy switchen keresztül kapcsolódnának egymáshoz, a switch kiesése működésképtelenné tenné a rendszert.

3 A replikáció működése

A PostgreSQL replikáció a WAL (Write Ahead Log) szegmensek átvitelén alapul. A WAL tömören annyi, hogy mielőtt egy tranzakciót érvényesítenénk az adatbazison (pl. egy rekordot beszúrnánk), a tranzakciót leíró WAL szegmenst egy olyan perzisztens tárra írjuk, ami áramkimaradás, rendszerleállás, egyszóval hiba esetén is hibátlanul visszaolvasható. Egy WAL fájl mérete tipikusan 16 Mb, de ettől más értéket is megadhatunk. A perzisztens tárra írás után az adatbázis feldolgozza a WAL fájlokat.

4 Replikáció fajtái

A replikáció fajtáit többféleképp is csoportosíthatjuk. Az egyik szempont lehetne az, hogy egyszerre hány adatbázist tudunk írni a clusterünkben, a másik hogy a replikáció során mennyire vannak szinkronban a szervereink.

4.1 Master - slave

A legegyszerűbb megvalósítás a master - slave alapú felállás. Ekkor a több adatbázisunkból mindig csak egyet írhatunk (master), viszont az olvasások történhetnek a master-ből vagy bármely csak olvasható (slave) adatbázisból. Ha egy load balancing célszoftvert is alkalmazunk, akkor megtehetjük azt, hogy az INSERT és UPDATE műveletek a master-re továbbítódjanak, míg az olvasások megoszlanak a slave-ek között.

4.2 Master - master avagy multi master

A másik felállás szerint az összes adatbázisba írhatunk és az egyes beírt rekordokat az adatbázisok maguk között replikálják. Ez a bonyolultabb eset, a PostgreSQL-ben nem található erre megvalósítás, de egyéb szoftverekkel elérhető (pl. Bucardo).

4.3 Fájl alapú

A fájl alapú replikáció a WAL fájlok átmásolásával érhető el. A master szerver az író/módosító műveletek hatására WAL fájlokat generál, ezeket a fájlokat kell átmásolni a slave szerverekre. Az átmásolást nekünk kell megoldani, erre általában rsync-et használnak. A hátránya, hogy explicit átmásolás nélkül nincs replikáció. Egy cron-ból történő rsync meg tudja oldani a másolást, de ez legalább egy perces késleltetést jelent és nem túl szép.

4.4 Streaming

A streaming replikáció során egy wal_sender nevű process fog elindulni a master szerverünkön, míg a slave-eken egy-egy wal_receiver. A céljuk a WAL szegmensek folyamatos átvitele a master-ről a slave-ekre.

4.5 Aszinkron

Aszinkron replikáció esetén a WAL fájloknak a masteren történő feldolgozása és a slave-ekre történp kiküldése között lehet egy kis késletetés. Ez azt jelenti, hogy egy író/módosító műveletet a master nyugtáz, azt ő végre is hajtotta, de a slave-eken még nem történt meg az írás/módosítás.

4.6 Szinkron

Szinkron replikáció esetén kijelölhetünk egy! (csakis egy) slave szervert, akivel a master szinkron kapcsolatot fog felépíteni. Szinkon kapcsolat alatt azt értem, hogy egy író/olvasó műveletet a master mindaddíg nem igazol vissza, míg azt a szinkron slave társa végre nem hajtotta. Ezis egy késletetést fog a rendszerbe vinni, hiszen a WAL szegmenst át kell másolni, ugyanazt a műveletet két helyen is végre kell hajtani, a szinkron slavenek vissza kell ígazolni és a master csak ezután tudja nyugtázni a tranzakciót. Ha ilyen replikáción gondolkodunk, mindenképp olyan slave-et válasszunk szinkron társnak a master mellé, ami minél gyorsabb és minél kisebb válaszidejű kapcsolaton elérhető. A példánkban egy közvetlen kapcsolat van a két szerver között, ez tökéletesen megfelel a célra. Minimális követelménynek tekinthető, hogy legalább egy LAN-on legyen a két szerver.

4.7 Kaszkádosított

A kaszkádosított replikáció egy kicsit kilóg a sorból abban az értelemben, hogy ez inkább replikációs terheléselosztásnak tekinthető. A PostgreSQL 9.2-es verziójától kezdődően használhatjuk, a segítségével nem kell az összes slave-nek a masterről replikálnia, az mintegy "hullám" végighaladhat a rendszerünkön. Képzeljünk el egy olyan esetet, amikor van van masterünk, mellette egy szinkron slave és az összes többi slave a szinkron slave-ről replikál. Ezzel a mastert jelentősen tehermentesítettük. Érezzük, hogy ez a feature főleg nagy clusterek építésekor hasznos.

5 Streaming aszinkron replikáció konfigurálása

Először is fel kell telepítenünk mindkét gépünkön a PostgreSQL-t:

apt-get install postgresql-9.1

Ez a parancs feltelepíti a szükséges függőségeket is, a konfigurációs állományokat a /etc/postgresql/9.1/main alá helyezi. A legfontosabb konfig fájl a postgresql.conf és a pg_hba.conf. Az előbbiben állíthatjuk be az postgresql paramétereit, az utóbbiban pedig a hozzáféréseket szabályozhatjuk a szolgáltatott adatbázisokhoz. Mindkét állományra szükségünk lesz a továbbiakban. Először is a master és a slave szerveren is állítsuk be, hogy a megfelelő IP címeken figyeljenek. Ehhez módosítsuk a postgresql.conf fájl ezen sorát

#listen_addresses = 'localhost'         # what IP address(es) to listen on;

erre:

listen_addresses = 'localhost, 172.16.0.1'              # what IP address(es) to listen on;

(természetesen az IP címeket az adott gépnek megfelelően kell behelyettesíteni.) A replikáció lebonyolítására szükségünk van egy felhasználóra, akinek a nevében ez folyni fog. Megtehetjük, hogy a beépített postgres usert használjuk, de ha törekszünk az épp elegendő szintű jogosultságok kiosztására (Principle of least privileges), akkor létre kell hoznunk egy új usert. Ehhez váltsunk át a postgres felhasználóra, indítsunk egy psql shellt és hozzuk létre a usert:

su - postgres
psql
CREATE ROLE replicator WITH REPLICATION ENCRYPTED PASSWORD 'vasbeton';

Ezzel a megoldással a replikáló userünknek pont annyi joga lesz, mint amire szüksége van. Egy user (role) létrehozásakor a pg_hba.conf fájlban fel kell vennünk egy rekordot, hogy milyen paraméterek mellett engedélyezzük a bejelentkezését. Adjuk hozzá tehát a masteren a pg_hba_conf állományhoz az alábbi sort:

host	replication	replicator	172.16.0.2/32	md5

Ez azt jelenti, hogy a replication adatbázishoz a replicator (ezt mi hoztuk létre) user a 172.16.0.2-es IP címről csatlakozhat, a jelszavát pedig md5 hashelve küldi el titkosítatlanul (közvetlen összeköttettésünk van, nem kell az SSL, egyéb esetben szükséges lenne). Most állítsuk be a masteren, hogy tudjon a hot standby párjáról. Ehhez szerkesszük a postgresql.conf fájlt:

wal_level = hot_standby # engedélyezi a read-only lekérdezéseket a host standby rendszeren
max_wal_senders = 5 # egyszerre max. ennyi standby szerver kapcsolódhat a masterre
wal_keep_segments = 16 # ennyi WAL szegmenst fog megőrizni a master a pg_xlog könyvtárban. \\
  Erre azért van szükség, hogy az online backup és a streaming replikáció megkezdése között \\ 
  nehogy törölje a master ezeket a fájlokat. A WAL szegmensek általában 16 MB méretűek.
# %f jelenti a fájlnevet, a %p pedig a path-t
archive_command = 'cp -i %p /var/lib/postgresql/9.1/main/pg_xlog/%f' # fontos, hogy a pg_xlog \\
  könyvtárat használjuk, mert ide kerülnek a WAL szegmensek
archive_mode = on

Ezután indítsuk el a masteren a portgrest és készítsünk róla egy backupot, amit átmásolunk a slave-re:

su - postgres
# az rsync miatt érdemes eljátszani a szervereink postgres felhasználói \\
  között az SSH kulcscserét. Akár egy scriptet is írhatunk a célra, megéri.
psql -c "SELECT pg_start_backup('label', true)"
cd /var/lib/postgresql/9.1/main
rsync -ave ssh /var/lib/postgresql/9.1/main/ 172.16.0.2:/var/lib/postgresql/9.1/main \\
  --exclude postmaster.opts  --exclude server.crt  --exclude server.key  --exclude postmaster.pid
psql -c "SELECT pg_stop_backup()"

Most térjünk vissza a slave szerverhez. A pg_hba.conf-hoz adjuk hozzá az alábbi sort:

host	replication	replicator	172.16.0.2/32	md5

A postgresql.conf-ban pedig állítsuk az elábbi sort:

hot_standby = off

erre:

hot_standby = on

Létre kell hoznunk egy recovery.conf állomány a $PGDATA alatt. Ez debian alaptelepítés esetén a /var/lib/postgresql/9.1/main. A recovery.conf tartalma legyen ez:

# streaming replikációnál mindig on
standby_mode          = 'on'

primary_conninfo      = 'host=172.16.0.1 port=5432 user=replicator password=vasbeton application_name=dbtest2'


# ez indítja a failovert
trigger_file = '/tmp/pgsql.trigger'

# a masteren lévő archive_command párja:
restore_command = 'cp -i /var/lib/postgresql/9.1/main/pg_xlog/%f %p'

Ha ezzel megvagyunk, a munka "aszinkron" része már készen is van. Indítsuk újra az adatbázisainkat, és nézzük meg az alábbi lekérdezést a masteren:

postgres=# select application_name, state, sent_location, write_location, sync_state from pg_stat_replication ;
 application_name |   state   | sent_location | write_location | sync_state 
------------------+-----------+---------------+----------------+------------
 walreceiver      | streaming | 0/8001650     | 0/8001650      | async
(1 row)

Láthatjuk, hogy a streaming aszinkron replikáció működik. Érdemes lehet megnézni a wal sender folyamatot a masteren:

root@dbtest1:~# ps ax | grep wal
1442 ?        Ss     0:00 postgres: wal writer process                                                                                         
1460 ?        Ss     0:00 postgres: wal sender process replicator 172.16.0.2(53859) streaming 0/8001650 

A slave-en a WAL receiver processt figyelhetjük meg:

root@dbtest2:~# ps ax  | grep wal
 1329 ?        Ss     0:00 postgres: wal receiver process   streaming 0/8001650 

6 Streaming szinkron replikáció konfigurálása

A szinkron replikáció beállítása az aszinkronéra épül, így először a fenti pont szerinti lépéseket kell végrehajtani. Ha ez kész, már szinte célbaértünk, hiszen csak egy-egy paramétert kell módosítani a masteren és a slave-en. Lássuk ezeket! A masteren a synchronous_standby_names paramétert kell beállítanunk a szinkron standby szerverünk nevére. Nem kell megegyeznie az FQDN-ével, látni fogjuk hogy a túloldalon is meg kell adnunk ezt a nevet. Az is megkötés, hogy egyszerre csak egy szinkron standby szerver kapcsolódhat a masterre.

synchronous_standby_names = 'dbtest2'

A slave oldalán szintén nagyon egyszerű a helyzet, a recovery.conf primary_connfinfo paraméterét kell bővítenünk egy application_name opcióval:

# aszinkron esetben:
#primary_conninfo      = 'host=172.16.0.1 port=5432 user=replicator password=vasbeton'
# szinkron esetben
primary_conninfo      = 'host=172.16.0.1 port=5432 user=replicator password=vasbeton application_name=dbtest2'
<pre>

Meg is volnánk :) Nézzük meg a masteren a pg_stat_replication view tartalmát, változott-e:
<pre>
postgres=# select application_name, state, sent_location, write_location, sync_state from pg_stat_replication;
application_name |   state   | sent_location | write_location | sync_state 
------------------+-----------+---------------+----------------+------------
 dbtest2          | streaming | 0/80016A8     | 0/80016A8      | sync
(1 row)

Érdekes tartalma van a lognak (/var/log/postgresql/postgresql-9.1-main.log) is (felül a frissebb bejegyzések):

2012-12-10 23:58:58 CET LOG:  standby "dbtest2" is now the synchronous standby with priority 1
2012-12-10 23:58:53 CET LOG:  incomplete startup packet
2012-12-10 23:58:53 CET LOG:  database system is ready to accept connections
2012-12-10 23:58:53 CET LOG:  autovacuum launcher started
2012-12-10 23:58:53 CET LOG:  database system was shut down at 2012-12-10 23:58:28 CET

Az incomplete startup packet rémisztő lehet, de azt a replikáló szerver okozza. A slave szerveren is érdemes szétnézni:

2012-12-10 23:58:58 CET LOG:  streaming replication successfully connected to primary
2012-12-10 23:58:58 CET LOG:  database system is ready to accept read only connections
2012-12-10 23:58:58 CET LOG:  consistent recovery state reached at 0/8001650

7 Magas rendelkezésre állás virtuális IP-vel

A nagyobb rendszereket üzemeltetők gyakran elgondolkodnak azon, hogyan tehetnék még megbízhatóbbá rendszerüket: mit tegyenek, egy szerver kiesése esetén, esetleg tudják-e ezt a cselekvést automatizálni. A következő bekezdés egy ilyen módszert ragad ki a sok megoldás közül.

7.1 Mi az a virtuális IP cím?

A virtuális IP cím (röviden VIP) egy olyan IP cím, ami nem kimondottan egy szerverhez vagy egy hálózati kártyához van rendelve, hanem több alkalmazás, szerver osztozik rajta. Ha egyidejűleg csak egyetlen géphez rendeljük hozzá, majd a gép kiesése esetén egy másik géphez ami képes átvenni a funkcióját, lényegében egy VIP alapú failover megoldást kapunk.

7.2 Hogyan tudom konfigurálni?

A VIP automatikus kezeléséhez a keepalived programot fogom használni. A keepalived egy "útválasztó" program, amivel terheléelosztást (loadbalancing) és magas rendelkezésreállást (High Availability - HA) tudunk megvalósítani. Egy adatbázis esetében a terheléselosztás nem olyan egyszerű feladat, mint egy webszerver esetében, ezért erre más megoldásokat szoktak használni (pl. pgpool). Itt én csak a HA rész beállítását fogom bemutatni.

7.3 Automatikus failover

A keepalived telepítéséhez futtassuk az alábbi parancsot a masteren és a slave-en egyaránt:

apt-get install keepalived

A /etc/keepalived alatt fogja keresni a keepalived.conf-ot, amit nekünk kell létrehoznunk. A master esetében a fájl tartalma legyen ez:

vrrp_instance VI_1 {
  # kezdeti állapot
  state MASTER
  interface eth0

  # egy NIC-et több vrrpd is használhat, ezzel lehet őket
  # megkülönböztetni
  virtual_router_id 1

  # master választáskor a minél magasabb prioritással lehetünk masterek
  # a dokumentáció szerint ha egy szervert nagyon szeretnénk masternek,
  # akkor a prioritása legyen 50-el magasabb mint a többié
  priority 100
  
  # ezt a paramétert itt is meg kell adni, hogy a "feltámadása" esetén 
  # ne vegye el a VIP-et a slave-től
  nopreempt

  # VIP
  virtual_ipaddress {
    192.168.100.100/24 dev eth0 label eth0:vip
  }
}

A slave esetén a keepalived.conf tartalma:

vrrp_instance VI_1 {
  # kezdeti állapot
  state BACKUP
  interface eth0

  # ha a slave megkapta a VIP-et és a master feléled, akkor is
  # megtartja a VIP-et
  nopreempt

  # egy NIC-et több vrrpd is használhat, ezzel lehet őket
  # megkülönböztetni
  virtual_router_id 1

  # master választáskor a minél magasabb prioritással lehetünk masterek
  # a dokumentáció szerint ha egy szervert nagyon szeretnénk masternek,
  # akkor a prioritása legyen 50-el magasabb mint a többié
  priority 50

  # VIP
  virtual_ipaddress {
    192.168.100.100/24 dev eth0 label eth0:vip
  }

  # slave -> master átmenet
  notify_master "/etc/keepalived/to_master.sh"
}

A to_master.sh pedig így néz ki:

#!/bin/bash

# létrehozza a triggerfájlt -> a slave masterre vált és írhatóvá válik
touch /tmp/pgsql.trigger


8 Teljesítménytesztek

8.1 Streaming szinkron replikáció

8.2 Streaming szinkron replikáció failoverrel

8.3 A failover tesztelése

Személyes eszközök