A MySQL replikációs és clusterezési lehetőségeinek bemutatása 2.
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 és 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 fürtözéssel ismertetjük meg olvasóinkat.
MySQL Cluster
Bemutatás
A MySQL-ben használt klaszterezési technológiában három különálló infrastrukturális feladatot ellátó kiszolgálót különböztetünk meg:
- Data node (Linux alatt a mysql-cluster-server-datanode csomag): feladata az adatbázisok tárolása, gondoskodik azok szinkronizációjáról, transzparens módon szolgálja ki az SQL node-okat, terheléselosztás révén gondoskodik a minél hatékonyabb működtetésről, valamint képes a leállást követő újraszinkronizációra.
- SQL node (vagy application node) (Linux alatt a mysql-cluster-server-sqlnode csomag, de ez megfelel a mysql-server csomagnak): Az alkalmazások felől elérhető kiszolgáló(k). Ők kezelik a data node-okról érkező adatfolyamokat és szolgálják ki az egyes eléréseket.
- Management node (Linux alatt a mysql-cluster-server-mgmtnode csomag): Konfigurációs felada-tok és monitorozás céljára szolgáló kiszolgáló(k). A klaszter indítása és leállítása során kiemelt szerepük van, addig nem csatlakoztatható egy gép data node-ként a klaszterbe, amíg legalább egy management node nem indult el.
MySQL-ben cluster csak NDB engine-el használható, amely jelenleg is számos megszorítást tartalmaz a többi népszerű adatbázis engine-hez képest, de ezek száma folyamatosan csökken.
A MySQL cluster lehetővé teszi, hogy a több data node-ból kialakított cluster-eket akár egymásra replikáljuk és az SQL node-ok számára transzparens módon szolgáltassunk a clusterek között váltogatva.
MySQL Cluster létrehozása
- A létrehozandó cluster-ben két data node-lesz:
db0ésdb1. - A load balancer-ként funkcionáló dedikált kiszolgáló:
mysql-proxy. - Mindkét node egyben management funkciókat is el fog látni. (Két management node-al nagyobb rendelkezésre állást tudunk megvalósítani, mivel bármelyik kiesése esetén a cluster továbbra is menedzselhető marad a másik által.)
- Létrehozunk egy MySQL Proxy-n alapuló load balancer eljárást.
- Végezetül felhasználói script-ekkel automatizáljuk a kiszolgálók elindulásának és a cluster felépítésének folyamatát.
Nem túl elterjedt, hogy egy kiszolgálón kerüljön kialakításra a management és a data node is, azonban a fenti konfigurációval (két data node, és mindkettő management is egyben) teljes értékű failover rendszer alakítható ki két kiszolgálóval is.
Előkészületek (ezt mindkét kiszolgálón meg kell tenni):
- hozzunk létre egy új felhasználói csoportot a kiszolgálókat futtató dedikált felhasználók számára:
groupadd mysql
- hozzunk létre egy, a mysql kiszolgálókat futtató felhasználót az előbbi csoportban:
useradd -g mysql mysql
- állítsuk be a megfelelő jogosultságokat a cluster telepítése során beállított adatok tárolását végző jegyzékeken:
chown mysql:root /opt/oracle/disk/mysql_cluster/mysqld_data
- next-next-finish módon csomagból telepítsük fel a MySQL Cluster-t, FONTOS: a telepítés végén ne indítsuk el a mysql-t!
1, Mindkét kiszolgálón módosítsuk a /etc/mysql/my.cnf konfigurációs állományt a következő módon:
[mysqld] basedir=/usr/local/mysql #az az adatkönyvtár amit a telepítés során megadtunk. datadir=/opt/oracle/disk/mysql_cluster/mysqld_data event_scheduler=on #csak ndb engine-el működik a cluster default-storage-engine=ndbcluster [ndbcluster] # a management node-ok nevei vagy ip címei felsorolva ndb-connectstring=db0,db1 key_buffer = 512M key_buffer_size = 512M sort_buffer_size = 512M table_cache = 1024 read_buffer_size = 512M [mysql_cluster] # a management node-ok nevei vagy ip címei felsorolva ndb-connectstring=db0,db1
2, Adjunk futási jogosultságot az ndb_mgm eszköznek a db0 kiszolgálón:
cd /usr/local/mysql chmod +x bin/ndb_mgm*
3, Hozzuk létre a cluster konfigurációs beállításait leíró állományt a db0 kiszolgálón:
mkdir /var/lib/mysql-cluster vim /var/lib/mysql-cluster/config.ini
4, Állítsuk be az alábbi paramétereket a 3. lépésben létrehozott fájl-ban:
[NDBD DEFAULT] NoOfReplicas=2 DataDir=/var/lib/mysql-cluster # fontos: induláskor az ndb ezt le is fogja foglalni! DataMemory=8G IndexMemory=4G [MYSQLD DEFAULT] [NDB_MGMD DEFAULT] [TCP DEFAULT] [NDB_MGMD] HostName=db0 # az első management node neve vagy ip címe NodeId=1 # az első management node azonosítója [NDB_MGMD] HostName=db1 # a második management node neve vagy ip címe NodeId=2 # a második management node azonosítója [NDBD] HostName=db0 # az első data node neve vagy ip címe NodeId=3 # az első data node azonosítója [NDBD] HostName=db1 # a második data node neve vagy ip címe NodeId=4 # a második data node azonosítója [MYSQLD] [MYSQLD]
5, A management node ezzel beállítva, elindítható. FONTOS, hogy első és csak az első indításkor az –initial paraméterrel kell indítani a ndb_mgmd -t a db0 kiszolgálón:
ndb_mgmd -f /var/lib/mysql-cluster/config.ini --initial --config-dir=/var/lib/mysql-cluster/
Ha mindent jól csináltunk, akkor a „MySQL Cluster Management Server verziószám„ üzenetet kell megkapunk.
6, Ismételjük meg a 2.-től 5.-ig lépéseket a db1 kiszolgálón is.
7, Indítsuk le a db0 kiszolgálón a data node-okat is:
/usr/local/mysql/bin/ndbd --initial
Ha mindent jól csináltunk, az
[ndbd] INFO -- Angel connected to 'localhost:1186' [ndbd] INFO -- Angel allocated nodeid: 3
üzenetet kell kapnunk.
8, Indítsuk el a db1 kiszolgálón is a data node-ot: ott értelem szerűen a nodeid: 4 üzenettel kell bejelentkeznie a data node-nak.
9, Indítsuk el mindkét kiszolgálón a mysql-t (az sql node-ot):
/etc/init.d/mysql.server start
10, Ahhoz, hogy a két clusteren külön-külön is tudjunk dolgozni, szükséges, hogy a mysql jogosultságai, felhasználói is NDB adatbázis engine-ben legyenek tárolva. Ehhez hajtsuk végre a következő módosításokat a db0 kiszolgálón:
use mysql; ALTER TABLE mysql.user ENGINE=NDBCLUSTER; ALTER TABLE mysql.db ENGINE=NDBCLUSTER; ALTER TABLE mysql.host ENGINE=NDBCLUSTER; ALTER TABLE mysql.tables_priv ENGINE=NDBCLUSTER; ALTER TABLE mysql.columns_priv ENGINE=NDBCLUSTER; ALTER TABLE mysql.procs_priv ENGINE=NDBCLUSTER; ALTER TABLE mysql.proxies_priv ENGINE=NDBCLUSTER;
11, Még mindig a db0 kiszolgáló MySQL adatbázisában dolgozva állítsuk be az esemény vezérlőt:
SET GLOBAL event_scheduler=1; CREATE EVENT `mysql`.`flush_priv_tables` ON SCHEDULE EVERY 30 second ON COMPLETION PRESERVE DO FLUSH PRIVILEGES;
12, Mivel a mysql adatbázisban tárolt jogosultságok még nem szinkronizálódtak át a db1-re (nem is tudnak átszinkronizálódni, mivel nincs meg hozzá a megfelelő jogosultságuk), azokat kézzel kell átvinnünk:
root@db0~# /etc/init.d/mysql.server stop root@db1~# /etc/init.d/mysql.server stop root@db0~# scp -r mysqld_data/ db1:/opt/oracle/disk/mysql_cluster/ root@db0~# /etc/init.d/mysql.server start root@db1~# /etc/init.d/mysql.server start
13, Ezek után ellenőrizzük le a cluster management-ben, hogy él a kapcsolat a node-ok között:
root@db0:~# ndb_mgm -- NDB Cluster -- Management Client -- ndb_mgm> show Connected to Management Server at: db0:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=3 @ipcím (verzió) id=4 @ipcím (verzió) [ndb_mgmd(MGM)] 2 node(s) id=1 @ipcím (verzió) id=2 @ipcím (verzió) [mysqld(API)] 2 node(s) id=5 @ipcím (verzió) id=6 @ipcím (verzió)
A MySQL Cluster működésének tesztelése
Hozzunk létre pár adatot a db0-n:
root@db0:~# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 mysql> use test Database changed mysql> CREATE TABLE testdata (i INT) ENGINE=NDBCLUSTER; mysql> INSERT INTO testdata () VALUES (1);
Ellenőrizzük le a meglétüket a db1-en:
root@db1:~# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 mysql> use test mysql> SELECT * FROM testdb; +------+ | i | +------+ | 1 | +------+ 1 row in set (0.00 sec)
Látható, hogy a két szerver szinkronizálta az adatokat egymás között.
Nézzük meg mi történik, ha leállítjuk a db0-s data node-ot:
root@db0:~# /etc/init.d/mysql.server stop root@db0:~# ndb_mgm -- NDB Cluster -- Management Client -- ndb_mgm> show Connected to Management Server at: db0:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=3 @ipcím (verzió) id=4 @ipcím (verzió) [ndb_mgmd(MGM)] 2 node(s) id=1 @ipcím (verzió) id=2 @ipcím (verzió) [mysqld(API)] 2 node(s) id=5 (not connected, accepting connect from any host) id=6 @ipcím (verzió)
A leállított db0 data node mellett hozzunk létre új adatokat a db1-en:
root@db1:~# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 4 mysql> use test; mysql> INSERT INTO testdb () VALUES (99); mysql> INSERT INTO testdb () VALUES (999); mysql> INSERT INTO testdb () VALUES (100);
Indítsuk el a db0-n a data node-ot és kérdezzük le az adatokat:
root@db0:~# /etc/init.d/mysql.server start root@db0:~# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 mysql> use test; mysql> SELECT * FROM testdb; +------+ | i | +------+ | 99 | | 999 | | 1 | | 100 | +------+ 4 rows in set (0.00 sec)
Mint látható az indulást követően szinkronizálódtak az adatok a két node között.
Load balancer MySQL Proxy-val
1, Telepítsük fel a MySQL Proxy-t és hozzuk létre a konfigurációs állományát a mysql-proxy kiszolgálón:
root@mysql-proxy:~# apt-get install mysql-proxy root@mysql-proxy:~# mkdir /etc/mysql-proxy root@mysql-proxy:~# cd /etc/mysql-proxy root@mysql-proxy:/etc/mysql-proxy# vim mysql-proxy.conf
2, Állítsuk be a létrehozott konfigurációs állományban a következőket:
[mysql-proxy] daemon = true keepalive = true # a proxy elérhetősége proxy-address = mysql-proxy:3306 # master (tehát írható / olvasható) adatbázis(ok) data node-ja(i) proxy-backend-addresses = db0:3306, db1:3306
3, Indítsuk el a MySQL Proxy-t:
root@mysql-proxy:~# <code>mysql-proxy</code> --defaults-file=/etc/mysql-proxy/mysql-proxy.conf
Indítás ütemezése, automatizálása
Mivel se az ndbb, se az ndb-mgmd nem indul el automatikusan, ráadásul a cluster data node-jai csak abban az esetben tudnak bejelentkezni a cluster-be, ha legalább egy management node-ot már látnak: szükséges ezek indítását automatizálni. Erre jó megoldás lehet az /etc/init.d/ jegyzékbe létrehozott indító script-ek használata. Fontos, hogy a következő fájl-ok létrehozása után futtatási jogot adjunk rájuk:
chmod +x /etc/init.d/<filename>
valamint az
update-rc.d <filename>
paranccsal érvénybe léptessük a változtatásokat.
Az ndbd indítására: /etc/init.d/ndbd
#!/bin/bash
# Provides: ndbd
# Required-Start: $local_fs $network $syslog $remote_fs
# Required-Stop: $local_fs $network $syslog $remote_fs
# Short-Description: mysql cluster manager client
# Description: mysql cluster manager client
ndbd_bin=/usr/local/mysql/bin/ndbd
if ! test -x $ndbd_bin; then
echo "Can't execute $ndbd_bin";
exit;
fi
start_ndbd(){
number_of_ndbd_pids=`ps aux|grep -iv "grep"|grep -i "/usr/local/mysql/bin/ndbd"|wc -l`
if [ $number_of_ndbd_pids -eq 0 ]; then
$ndbd_bin
echo "ndbd started."
else
echo "ndbd is already running."
fi
}
stop_ndbd(){
number_of_ndbd_pids=`ps aux|grep -iv "grep"|grep -i "/usr/local/mysql/bin/ndbd"|wc -l`
if [ $number_of_ndbd_pids -ne 0 ]; then
ndbd_pids=`pgrep ndbd`
for ndbd_pid in $(echo $ndbd_pids); do
kill $ndbd_pid 2> /dev/null
done
number_of_ndbd_pids=`ps aux|grep -iv "grep"|grep -i "/usr/local/mysql/bin/ndbd"|wc -l`
if [ $number_of_ndbd_pids -eq 0 ]; then
echo "ndbd stopped."
else
echo "Could not stop ndbd."
fi
else
echo "ndbd is not running."
fi
}
case "$1" in
'start' )
start_ndbd
;;
'stop' )
stop_ndbd
;;
'restart' )
stop_ndbd
start_ndbd
;;
*)
echo "Usage: $0 {start|stop|restart}" >&2
;;
esacAz ndb-mgmd indítására: /etc/init.d/ndb-mgmd
#!/bin/bash
# Provides: ndb_mgmd
# Required-Start: $local_fs $network $syslog $remote_fs
# Required-Stop: $local_fs $network $syslog $remote_fs
# Short-Description: mysql cluster manager
# Description: mysql cluster manager
ndb_mgmd=/usr/local/mysql/bin/ndb_mgmd
config_file=/var/lib/mysql-cluster/config.ini
config_dir=/var/lib/mysql-cluster
if ! test -x $ndb_mgmd; then
echo "Can't execute $ndb_mgmd"
exit;
fi
start_ndb_mgmd(){
number_of_ndb_mgmd_pids=`ps aux|grep -iv "grep"|grep -i "$ndb_mgmd"|wc -l`
if [ $number_of_ndb_mgmd_pids -eq 0 ]; then
$ndb_mgmd -f $config_file --config-dir=$config_dir
echo "ndb_mgmd started."
else
echo "ndb_mgmd is already running."
fi
}
stop_ndb_mgmd(){
number_of_ndb_mgmd_pids=`ps aux|grep -iv "grep"|grep -i "$ndb_mgmd"|wc -l`
if [ $number_of_ndb_mgmd_pids -ne 0 ]; then
ndb_mgmd_pids=`pgrep ndb_mgmd`
for ndb_mgmd_pid in $(echo $ndb_mgmd_pids); do
kill $ndb_mgmd_pid 2> /dev/null
done
number_of_ndb_mgmd_pids=`ps aux|grep -iv "grep"|grep -i "$ndb_mgmd"|wc -l`
if [ $number_of_ndb_mgmd_pids -eq 0 ]; then
echo "ndb_mgmd stopped."
else
echo "Could not stop ndb_mgmd."
fi
else
echo "ndb_mgmd is not running."
fi
}
case "$1" in
'start' )
start_ndb_mgmd
;;
'stop' )
stop_ndb_mgmd
;;
'restart' )
stop_ndb_mgmd
start_ndb_mgmd
;;
*)
echo "Usage: $0 {start|stop|restart}" >&2
;;
esacA mysql-proxy indítására: /etc/init.d/mysql-proxy
#! /bin/bash
# Required-Start: $local_fs $network $syslog $remote_fs
# Required-Stop: $local_fs $network $syslog $remote_fs
# Short-Description: MySQL Proxy
# Description: MySQL Proxy
mysql_proxy=/usr/bin/mysql-proxy
config_file=/etc/mysql-proxy/mysql-proxy.conf
if ! test -x $mysql_proxy; then
echo "Can't execute $mysql_proxy"
exit;
fi
start_mysql_proxy(){
number_of_mysql_proxy_pids=`ps aux|grep -iv "grep"|grep -i "/usr/bin/mysql-proxy"|wc -l`
if [ $number_of_mysql_proxy_pids -eq 0 ]; then
$mysql_proxy --defaults-file=$config_file
echo "mysql-proxy started."
else
echo "mysql-proxy is already running."
fi
}
stop_mysql_proxy(){
number_of_mysql_proxy_pids=`ps aux|grep -iv "grep"|grep -i "/usr/bin/mysql-proxy"|wc -l`
if [ $number_of_mysql_proxy_pids -ne 0 ]; then
mysql_proxy_pids=`pgrep mysql-proxy`
for mysql_proxy_pid in $(echo $mysql_proxy_pids); do
kill $mysql_proxy_pid 2> /dev/null
done
number_of_mysql_proxy_pids=`ps aux|grep -iv "grep"|grep -i "/usr/bin/mysql-proxy"|wc -l`
if [ $number_of_mysql_proxy_pids -eq 0 ]; then
echo "mysql-proxy stopped."
else
echo "Could not stop mysql-proxy."
fi
else
echo "mysql-proxy is not running."
fi
}
case "$1" in
'start' )
start_mysql_proxy
;;
'stop' )
stop_mysql_proxy
;;
'restart' )
stop_mysql_proxy
start_mysql_proxy
;;
*)
echo "Usage: $0 {start|stop|restart}" >&2
;;
esac


