PostgreSQL adatbázis replikálás
A nemrég látott előadás kapcsán felmerült bennem, hogy ki kéne próbálni, hogyan lehet adatbázist replikálni. Mert olyat még nem csináltam, legalábbis eddig.
Mire is lehet ez jó? Először is biztonságos, ha kiesik egy gép, akkor sincs nagy katasztrófa, mert van másik, ami ráadásul eléggé up-to-date. Ami viszont szintén nem elhanyagolható dolog, az a terheléselosztás, azaz van pl. egy master replikánk, amibe mennek a módosítások (INSERT, DELETE, UPDATE), és van több slave egységünk, amiket lehet kérdezgetni (SELECT). Egy tipikus alkalmazás esetében a kérdezgetések száma nagyságrendekkel nagyobb ugyebár.
Na lássuk, hogy megy a dolog, ha postgresql szervert szeretnénk használni:
A próbát Solaris 10 alatt csináltam, egy gépen felhúztam gyorsan két zónát (pgmaster és pgslave), amiknek a /opt könyvtáruk is közös volt a global zónáéval, így a dolgokat csak egyszer kellett lefordítanom, és megvoltak egyből mindenhol. PostgreSQL-ből letöltöttem a legújabbat, biztos ami biztos, gond nélkül fordult. Többféle replikációs szoftver is van postgreshez, nekem a Slony-I volt a legszimpatikusabb, ezért azt töltöttem és fordítottam le. (A Solarishoz adott bison valamiért segfaultolt, de a sunfreeware-ről töltöttel simán fordult ez is.)
A postgresql konfigurációjánál annyira kell odafigyelni, hogy mindkét gép elérje a másikon futó adatbázis szervert, ehhez annyi kell, hogy a pg_hba.conf aljára beszúrjuk mindkét gépet a megfelelő módon.
Csináljunk egy adatbázist, amit majd replikálunk. A könnyebbség kedvéért beállítottam néhány környezeti változót:
export CLUSTERNAME=proba export MASTERDBNAME=cica export SLAVEDBNAME=cica export MASTERHOST=192.168.7.64 export SLAVEHOST=192.168.7.65 export PGUSER=cica export REPLICATIONUSER=postgres export REPLICATIONPASS=jelszo
A replikálást végző felhasználónak mindenféle jog kell postgres oldalon, ezért én az alap postgres usert használtam, de élesben persze van értelme új felhasználót létrehozni.
Az adatbázist és a táblákat is meg kell csinálni mindkét oldalon, mert az adatbázis sémát nem viszi át a slony, csak az adatokat. (Tehát akinél percenként fut az ALTER TABLE, annak ez nem jó megoldás, de ő egyébként is gondolkozzon el a programozási technikáján
)
$ createuser -A -D $PGUSER $ createdb -O $PGUSER adatbázis $ createlang plpgsql cica $ psql postgres=# create table probatabla (id serial primary key, szoveg varchar(200)); CREATE TABLE
Egy rövidke scripttel a master oldalon felkonfiguráljuk a slony-t, hogy tudja, mit kell neki replikálni:
#!/bin/sh slonik < <_EOF_ # sema nev cluster name = $CLUSTERNAME; # admin kapcsolatadatok a szerverekhez node 1 admin conninfo = 'dbname=$MASTERDBNAME host=$MASTERHOST user=$REPLICATIONUSER password=$REPLICATIONPASS'; node 2 admin conninfo = 'dbname=$SLAVEDBNAME host=$SLAVEHOST user=$REPLICATIONUSER password=$REPLICATIONPASS'; # az 1-es csomopont inicializalasa, ez a parancs letrehozza a _semat, es benne a replikalashoz szukseges dolgokat init cluster ( id=1, comment = 'Master Node'); # halmazokba (set) kell rendezni a tablainkat, amiket replikalni akarunk # egy adott slave egy halmazra tud "feliratkozni" create set (id=1, origin=1, comment='proba tabla egyedul'); set add table (set id=1, origin=1, id=1, fully qualified name = 'public.probatabla', comment='proba tabla'); # masodik node elkeszitese, kapcsolodasi informaciok store node (id=2, comment = 'Slave node'); store path (server = 1, client = 2, conninfo='dbname=$MASTERDBNAME host=$MASTERHOST user=$REPLICATIONUSER password=$REPLICATIONPASS'); store path (server = 2, client = 1, conninfo='dbname=$SLAVEDBNAME host=$SLAVEHOST user=$REPLICATIONUSER password=$REPLICATIONPASS'); _EOF_
Ezután a mindkét oldalon indulhat is a slon. (Ez persze jó, ha a gép újraindításakor a postgres elindulása után maga is elindul.)
pgmaster# slon $CLUSTERNAME "dbname=$MASTERDBNAME user=$REPLICATIONUSER host=$MASTERHOST password=$REPLICATIONPASS"
pgslave# slon $CLUSTERNAME "dbname=$SLAVEDBNAME user=$REPLICATIONUSER host=$SLAVEHOST password=$REPLICATIONPASS"
Annyit kell már csak tennünk, hogy a slave-vel feliratkozunk arra a set-re, amit replikálni szeretnénk:
#!/bin/sh slonik < <_EOF_ # sema nev cluster name = $CLUSTERNAME; # admin kapcsolat leirok node 1 admin conninfo = 'dbname=$MASTERDBNAME host=$MASTERHOST user=$REPLICATIONUSER password=$REPLICATIONPASS'; node 2 admin conninfo = 'dbname=$SLAVEDBNAME host=$SLAVEHOST user=$REPLICATIONUSER password=$REPLICATIONPASS'; # a 2-es node feliratkozik az 1-es node 1-es set-jere, amit nem tovabbit subscribe set ( id = 1, provider = 1, receiver = 2, forward = no); _EOF_
Igazából ennyi. Ezt meg lehet csinalni jó sok géppel, akár több szinten is. Nézzük, hogy sikerült-e a művelet:
Master oldalon beleteszünk valamit a táblánkba:
cica=# insert into probatabla (szoveg) values ('ez itt a szoveg');
INSERT 0 1
És nézzük meg az eredményt a slave oldalon:
cica=# select * from probatabla; id | szoveg ----+-------------- 1 | szoveg (1 row)
Ottvan. Örül!
A Django 1.1 tervei között szerepel az ilyen master-slave (illetve más jellegű) adatbázis replikák támogatása, sok jó ötlet szóba került, majd meglátjuk mi lesz belőle, a djangós srácokban eddig nem csalódtam (pedig nincs is komoly szakálluk!
). Hajrá!