A MySQL replikációs és clusterezési lehetőségeinek bemutatása 1.
Munkánk során gyakran kerülünk olyan helyzetbe, amikor a normál felhasználási szokásoknál alkalmazott módszerek nem működőképesek, nem nyújtanak megfelelő szolgáltatásokat. Ilyenkor kell sokkal hibatűrőbb, nagyobb rendelkezésre állású rendszereket terveznünk, készítenünk, amelyek egyik fontos építő eleme az adatokat kiszolgáló relációs adatbázis-kezelő. Ma már az ingyenes MySQL is hatékony replikációs és fürtözési technológiákat biztosít a rendszertervezők/fejlesztők felé, jelen cikkünkben ezek közül a replikációval ismertetjük meg olvasóinkat.
MySQL Replikáció
Bemutatás
A MySQL-ben meglévő replikációs megoldások olyan esetekben használhatók, amikor akár biztonsági másolat, akár terheléselosztás céljából szükséges egy vagy több adatbázis automatikus egyirányú szinkronizációja. Gyakori, hogy nagy forgalmú – elsősorban közösségi jellegű Internetes – alkalmazásoknál az adatbázis írási műveletek egy ún. master adatbázison hajtódnak végre, míg a nagyságrendekkel nagyobb számú lekérdezési művelet a master-ekről szinkronizált nagyobb számú slave adatbázis kiszolgálókról kerül végrehajtásra. Nagyobb terhelésű adatbázis kiszolgálók esetében az ütemezett automatikus mentések replikált slave-ről történő végrehajtása is csökkentheti a master kiszolgáló terhelését.
A MySQL beépített replikációs megoldásának alkalmazásával csak egy master kiszolgáló lehet, de több slave is csatlakozhat hozzá. Több slave alkalmazásánál a replikáció párhuzamosan hajtódik végre. A replikáció során a master-en a maximális adatbázis kapcsolatok számába bele számít(anak) a replikációs user(ek) csatlakozása(i)!
A replikáció egy irányú: a slave-en létrehozott önálló adatbázistáblák nem kerülnek replikációra a master-en! (Más kérdés, hogy nem „illik” replikált táblán írási műveletet végrehajtani slave oldalon, sőt lehetőség szerint ez tiltani is kell, lásd a
FLUSH TABLES WITH READ LOCK;
és a
SET GLOBAL read_only = ON;
utasításokat.)
Ha a slave kiesik a szinkronból, akkor a következő indulásakor (a slave kiszolgáló mysqld service-ének indulásakor) feldolgozza az addig keletkezett master binlog adatokat, így ilyenkor kell egy kis idő, amíg „utoléri” magát.
Ha a master kiesik a szinkronból, a slave az utolsó commit-ig tartalmaz mindent, így read-only kiszolgálóként használható. (Érdemes erre felkészíteni az alkalmazásunk (amennyiben az alkalmazott üzleti logika ezt megengedi): a felhasználók számára az olvasási műveleteket továbbra is elérhetővé tenni, míg az adatbázis írási műveletekkel járó felhasználói interakciókat erre az időszakra letiltani.)
Alapesetben a master-en tranzakció szintű izolációs szint szerinti replikáció valósul meg, tehát minden elkezdett tranzakció a bináris logba bekerül, s végrehajtása után (és ha nem volt rollback) kezdi meg a binlog-ból a replikációt. Így a slave-en folyamatosan konzisztens marad az adatbázis: csak a lezárt tranzakciók kerülnek át.
Amennyiben mélyebb izolációs szintre szeretnénk vinni a replikációt (tranzakción belüli műveleteket is replikálni, illetve nem tranzakciós adatbázist (pl. MyISAM) replikálni), úgy a binlog_direct_non_transactional_updates
globális változó értékadásával megtehetjük ezt. FONTOS: ilyen esetekben a replikáció jóval nagyobb adatforgalommal és feldolgozandó bináris log mennyiséggel jár!
Tranzakciós master adatbázist lehet nem tranzakciós slave-be replikálni, de visszafelé ez már nem igaz. Ennek ellenére javasolt a két adatbázisnak azonos DB engine-el rendelkeznie. Ha mégis eltérő DB engine-ket kell használnunk, akkor a kialakításban ismertetett 6. lépés során a slave-en történő adatbetöltés után az
ALTER TABLE ... ENGINE=engine_type;
utasítással tudjuk az egyes táblákat átállítani az új engine-re, majd a
SET default_storage_engine=engine_type;
utasítással az adatbázis alapértelmezett engine-jét is be tudjuk állítani.
A MySQL replikáció kialakításánál mindig (!) a master elindítása és rendelkezésre állása után kell manuálisan (vagy a slave-en létrehozott, indítási script segítségével) létrehozni a replikációt és a szinkronizációt az aktuális bináris log pozíció alapján.
Megvalósítás
Két, VirtualBox-ban futtatott Debianra (7.6-os verzió, i386) telepítettem egy-egy MySQL kiszolgálót. A két virtualizált számítógép mysqlmaster
és mysqlslave
nevekkel lett létrehozva, mindkettő a VirtualBox ún. host-olt hálózati kártya szolgáltatásán keresztül volt elérhető ez által biztosítva, hogy elérjék egymást is és a host gépet is.
Megjegyzés: ebben a hálózati kártya üzemmódban a host-olt gép, mint DHCP kiszolgáló két 192.168.56.*-ban végződtetett IP címet oszt ki a két virtualizált számítógépnek, kívülről (gazdagéptől felfelé) a két gép nem látszik és nem elérhető.
Az alábbiakban ismertetett megoldás során egyedileg, MySQL konzolból futási időben hozzuk létre a replikációt.
1, A mysqlmaster
kiszolgálón le kell állítani a mysqld service-t:
$ sudo service mysql stop
2, A mysqlmaster
kiszolgálón a(z) /etc/mysql/my.cnf
állományban be kell állítani a következőket:
#tetszőleges egyedi azonosító szám is szerepelhet itt (legjobb példa pl a kiszolgáló #IP címét használni pontok nélkül). server-id = 19216856101 #a mysql adatbázis (vagy mások is) log-ból való kizárása replikáció szempontjából binlog_ignore_db = mysql
3, A mysqlmaster
kiszolgálón el kell indítani a mysqld service-t:
$ sudo service mysql start
4, Létre kell hozni egy, a replikációra szolgáló usert és engedélyezni kell a távoli hozzáférést (a példában bármely host-ról engedélyezzük, a gyakorlatban ezt célszerű egy dedikált IP címre szűkíteni):
CREATE USER replicant@'%' IDENTIFIED BY 'password'; GRANT SELECT, PROCESS, FILE, SUPER, REPLICATION CLIENT, REPLICATION SLAVE, RELOAD ON *.* TO replicant@'%'; FLUSH PRIVILEGES;
5, A mysqlslave
kiszolgálón le kell állítani a mysqld service-t:
$ sudo service mysql stop
6, A mysqlslave
kiszolgálón a(z) /etc/mysql/my.cnf
állományban be kell állítani a következőket:
#tetszőleges egyedi azonosító szám is szerepelhet itt, ami eltér a master-étől #(legjobb példa pl a kiszolgáló IP címét használni pontok nélkül) server-id = 19216856102
7, Hozzuk létre a mysqlmaster
kiszolgálón a replikálni kívánt adatbázist, töltsük fel adatokkal, majd mysqldump
-al másoljuk át a mysqlslave
kiszolgálóra (amin előtte el kell indítani a mysqld-t.) és importáljuk be. Így a két adatbázis kiszolgáló adattartalma most megegyezik.
8, A mysqlmaster
kiszolgálón futtassuk le a következő SQL parancsot (lock-oljuk a táblákat, hogy a master-slave kapcsolat kiépüléséig ne írhassanak bele):
FLUSH TABLES WITH READ LOCK;
9, A mysqlmaster
kiszolgálón futtassuk le a következő SQL parancsot:
SHOW MASTER STATUS;
Az eredményből jegyezzük meg a file és position adattagokat!!!
10, A mysqlslave
kiszolgálón biztos ami biztos, állítsuk le a replikációt (elvileg még be sem kapcsoltuk, de nem árt leellenőrizni ezzel az SQL utasítással):
STOP SLAVE;
11, A mysqlslave
kiszolgálón futtassuk le a következő SQL parancsot a replikációt beállítandó (itt a 9-es lépésben megkapott file és position értékeket kell használni):
CHANGE MASTER TO MASTER_HOST='név vagy ip cím', MASTER_USER='replicant', MASTER_PASSWORD='password', MASTER_LOG_FILE='file', MASTER_LOG_POS=position; START SLAVE; SHOW SLAVE STATUS;
Ha mindent jól csináltunk, akkor az utolsó parancs status sorában a „Waiting for master to send event.”
üzenettel kell, hogy a mysqlslave
visszajelezze: működik a replikáció.
12, A mysqlmaster
kiszolgálón futtassuk le a következő SQL parancsot (a 8-as pontban létrehozott lock-olás feloldására):
UNLOCK TABLES;
A master-slave kapcsolat biztonságos leállítása
1, A mysqlslave
kiszolgálón állítsuk le a replikációt:
STOP SLAVE;
2, A mysqlslave
kiszolgálón írjuk ki a változásokat:
FLUSH TABLES;
3, Most már leállítható a mysqlslave
kiszolgáló:
/etc/init.d/mysql stop
A master-slave kapcsolat biztonságos elindítása
1, A mysqlslave
kiszolgálón indítsuk el a mysql-t:
/etc/init.d/mysql start
2, A mysqlslave
kiszolgálón indítsuk el a slave kapcsolatot:
START SLAVE;
3, Ellenőrizzük le, hogy működik-e:
SHOW SLAVE STATUS;
Monitorozás
A MySQL kiszolgálók között kialakított master-slave replikációk monitorozása megoldható a következők használatával:
- manuálisan a
SHOW GLOBAL STATUS like 'slave_running';
és a
SHOW SLAVE STATUS;
utasítások valamint az ezekre épülő egyedi script-ek használatával,
- a Persona Toolkit használatával,
- a MySQL Enterprise Monitor használatával,
- vagy a MONyog – MySQL Monitoring Tool használatával.
Példák
SSL használata a replikáció során
Alapesetben a MySQL-ben a replikáció nem használ SSL protokolt az adatok átvitele során, azonban a /etc/mysql/my.cnf
-ben ez beállítható. FONTOS: a master-slave replikáció felépítése előtt kell ezt végrehajtani!
Az SSL beállításának lépései:
1, Első lépésként ellenőrizzük mindkét serveren, hogy támogatja-e az SSL-t (Linux konzolban kiadandó shell parancs):
$ sudo mysqld --ssl –help
2, SSL certificate-ek létrehozása az mysqlmaster
kiszolgálón a /etc/mysql/certs
jegyzékbe:
$ sudo su $ apt-get install openssl $ cd /etc/mysql $ mkdir certs $ cd certs
3, Létrehozzuk a CA certificate-et a mysqlmaster
kiszolgálón 1000 napos lejárati dátummal:
$ openssl genrsa 2048 > ca-key.pem $ openssl req -new -x509 -nodes -days 1000 -key ca-key.pem > ca-cert.pem
4, Létrehozzuk a mysqlmaster
kiszolgálón a master certificate-jét 1000 napos lejárati dátummal és a CA felhasználásával:
$ openssl req -newkey rsa:2048 -days 1000 -nodes -keyout master-key.pem > master-req.pem $ openssl x509 -req -in master-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > master-cert.pem
5, Létrehozzuk a mysqlmaster
kiszolgálón a slave certificate-jét 1000 napos lejárati dátummal és a CA felhasználásával:
$ openssl req -newkey rsa:2048 -days 1000 -nodes -keyout slave-key.pem > slave-req.pem $ openssl x509 -req -in slave-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > slave-cert.pem
6, A mysqlmaster
kiszolgálón a /etc/mysql/my.cnf
-ben beállítjuk a tanúsítványok használatát:
[mysqld] ssl-ca=/etc/mysql/certs/ca-cert.pem ssl-cert=/etc/mysql/certs/master-cert.pem ssl-key=/etc/mysql/certs/master-key.pem
7, Újraindítjuk a mysqlmaster
-en a MySQL-t:
$ sudo service mysql stop
8, Leellenőrizzük a mysqlmaster
-en, hogy SSL-el lehet-e kapcsolódni a MySQL-hez:
$ sudo mysql -u root -p --ssl-ca=/etc/mysql/certs/ca-cert.pem
mysql> SHOW STATUS LIKE 'ssl_cipher'; +---------------+--------------------+ | Variable_name | Value | +---------------+--------------------+ | Ssl_cipher | DHE-RSA-AES256-SHA | +---------------+--------------------+ 1 row in set (0.00 sec) mysql> exit;
9, A replikációs user létrehozásánál használjuk a REQUIRE SSL;
kapcsolót is.
10, A mysqlslave
kiszolgálón létrehozzuk a /etc/mysql/certs
jegyzéket és átmásoljuk bele a slave-*.pem
állományokat.
11, A mysqlslave
kiszolgálón a /etc/mysql/my.cnf
-ben beállítjuk a tanúsítványok használatát:
[mysqld] ssl-ca=/etc/mysql/certs/ca-cert.pem ssl-cert=/etc/mysql/certs/slave-cert.pem ssl-key=/etc/mysql/certs/slave-key.pem
12, A master-slave kapcsolat felépítése során szintén meg kell adni az SSL használatának paramétereit, pl:
CHANGE MASTER TO MASTER_HOST='név vagy ip cím', MASTER_USER='replicant', MASTER_PASSWORD='password', MASTER_LOG_FILE='file', MASTER_LOG_POS=position, MASTER_SSL=1, MASTER_SSL_CA = 'ca-cert.pem', MASTER_SSL_CAPATH = '/etc/mysql/certs', MASTER_SSL_CERT = slave-cert.pem', MASTER_SSL_KEY = 'slave-key.pem';
Időzített replikáció – késleltetés
A slave-en beállítható a
CHANGE MASTER TO MASTER_DELAY = N;
utasítással (N a késleltetés ideje másodpercben). Ilyen esetekben N másodperc után kerülnek csak feldolgozásra a master binlogjába kerülő tranzakciók. Használata főleg a gyakori rollback-et alkalmazó üzleti rendszereknél hatásos.
Terheléselosztás
Forrás: MySQL dokumentáció – 17.3.3 Using Replication for Scale-Out
A fenti ábrán látható a leggyakoribb felhasználási módja a master-slave replikációnak. Ilyen esetekben szükséges, hogy az alkalmazásunk és a MySQL kiszolgálók közé beékeljünk egy ún. load balancer / terhelés elosztó réteget is. Erre MySQL környezetben a MySQL Proxy alkalmazás is felhasználható más LB megoldásokon (pl. HAProxy) kívül.
A MySQL Proxy konfigurációjában a proxy-read-only-backend-addresses
érték beállításával szabályozható, hogy az olvasási lekérdezések csak a slave-ekről szolgálhatók ki, a master-t pedig a proxy-backend-addresses
kulcshoz rendeljük.
Eltérő adatbázisok replikációja külön slave-ekre
Ha egy master adatbázis kiszolgálóról különböző adatbázisokat más-más slave adatbázis kiszolgálóra kívánunk replikálni, akkor a következőket kell beállítani:
Forrás: MySQL dokumentáció – 17.3.4 Replicating Different Databases to Different Slaves
Tilos a --replicate-do-db
kapcsoló használata az egyes slave-eken, helyette a --replicate-wild-do-table=databaseA.%.
beállítással kell megadni, hogy a databaseA adatbázist replikálja.
Ilyen esetekben minden slave ugyanazt a közös master binlog-ot olvassa fel, de mindegyik csak a saját beállításaiban megadott adatbázisokra vonatkozó műveleteket hajtja végre.
Egyszerre master-ként és slave-ként működő kiszolgáló
Egy adatbázis kiszolgáló lehet egyszerre master is és slave is. Pl. az alábbi példában a Master1 „hot backup”-ja a Master2, amire terhelés elosztás miatt 3 darab slave csatlakozik:
Forrás: MySQL dokumentáció – 17.3.5 Improving Replication Performance
Ilyen esetekben a Master2-n a --log-slave-updates
kapcsolóval engedélyezni kell, hogy az általa replikált adatokból új binlog-ot képezzen a slave-ek számára.
Failover hibatűrő rendszer kialakítása
Alapértelmezés szerinti működés:
Forrás: MySQL dokumentáció – 17.3.6 Switching Masters During Failover
Helyes konfiguráció esetén a Master kiesése esetén a Slave1 (vagy más, dedikált kiszolgáló) automatikusan átveszi a szerepét:
Forrás: MySQL dokumentáció – 17.3.6 Switching Masters During Failover
Ennek konfigurációjához azonban az ún. „Global Transaction Identifiers – GTIDs” technikát kell használni a MySQL-ben, bővebben lásd a MySQL dokumentációt.