Příprava systému
Vytvoříme db superuživatele slony:
sanatana# su - pgsql $ createuser -a -d -P slony Enter password for new user: Enter it again: CREATE USER $ exit
Přihlásíme se jako unixový uživatel slony a vytvoříme dvě databáze s nainstalovaným procedurálním jazykem pl/PgSQL. Je ovšem možné bez rizika použít i databáze stávající, protože všechny db objekty replikačního systému se instalují do samostatného schema, a jdou proto snadno zlikvidovat. Navíc má i konfigurační program slonik příkaz pro deinstalaci systému z databáze.
sanatana# su - slony FreeBSD is started up by the program 'init'. The first thing init does when starting multiuser mode (ie, starting the computer up for normal use) is to run the shell script /etc/rc. By reading /etc/rc, you can learn a lot about how the system is put together, which again will make you more confident about what happens when you do something with it. %createdb master CREATE DATABASE %createdb slave1 CREATE DATABASE %createlang plpgsql master %createlang plpgsql slave1 %
Protože replikaci budeme v praxi používat na již existující tabulky, vytvoříme si nějaká data, k čemuž dobře poslouží benchmarkovací program pgbench z distribuce Postgresu. Nakrmíme master databázi půl milionem řádků.
%pgbench -i -s 5 master
creating tables...
10000 tuples done.
500000 tuples done.
set primary key...
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "branches_pkey" for table "branches"
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "tellers_pkey" for table "tellers"
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "accounts_pkey" for table "accounts"
vacuum...done.
%
Připravíme si template soubor obsahující hesla superuživatelů, která bude administrativní program slonik potřebovat pro připojení do jednotlivých DB. Do tohoto souboru budeme později zadávat konfigurační příkazy (pochopitelně za příkaz NODE a současně před příkaz EXIT).
%cat setup.slonik
CLUSTER NAME = dharma;
NODE 1 ADMIN CONNINFO = 'host=localhost user=slony password=iehovah dbname=master';
NODE 2 ADMIN CONNINFO = 'host=localhost user=slony password=iehovah dbname=slave1';
EXIT 0;
%
Clustery
Databáze spřátelené za účelem replikace jsou organizovány do clusterů. Jedna databáze může být současně členem více clusterů, naopak cluster může mít právě jednu řídící master databázi. V terminologii slony se jednotlivé databáze zapojené do clusteru nazývají uzly – NODE – nezávisle na tom, zda běží pod stejným postmasterem, nebo ne. Master databáze clusteru musí být na uzlu s pořadovým číslem 1. Master je velmi důležitý. Jednotlivé slave uzly lze do clusteru přidávat a odebírat, nelze však přehodit status clustermaster z jednoho uzlu na druhý, aniž bychom museli zlikvidovat celý cluster. Znovuvytvoření clusteru není zase tak náročná operace. Pokud jste si schovávali kopie konfiguračních příkazů pro slonika, odpovídá doba překonfigurování clusteru odpovídá době potřebné k resynchronizaci databází.
Status Master databáze v clusteru nemá nic společného se zdrojem dat pro replikaci, data lze replikovat i mezi jednotlivými slave databázemi nebo směrem slave – master. Jak již bylo v úvodu řečeno, Slony je single-master replikační systém. To znamená, že pokud replikujeme set tabulek, je možné do tohoto setu zapisovat právě na jednom NODE. Nezáleží na tom, zda má tento node v clusteru status master, nebo slave.
Provedeme inicializace clusteru. Na taktické místo v souboru setup.slonik přidáme příkaz: ` INIT CLUSTER ; ` a spustíme
%slonik < setup.slonik %
V master databázi (NODE 1) bylo vytvořeno nové schema pojmenované podle clusteru a obsahující systémové tabulky replikátoru.
%psql master master-# \dn List of schemas Name | Owner --------------------+------- _dharma | slony master=# set search_path='_dharma'; SET master=# \dt List of relations Schema | Name | Type | Owner ---------+----------------+-------+------- _dharma | sl_config_lock | table | slony _dharma | sl_confirm | table | slony _dharma | sl_event | table | slony _dharma | sl_listen | table | slony _dharma | sl_log_1 | table | slony _dharma | sl_log_2 | table | slony _dharma | sl_node | table | slony _dharma | sl_path | table | slony _dharma | sl_seqlog | table | slony _dharma | sl_sequence | table | slony _dharma | sl_set | table | slony _dharma | sl_setsync | table | slony _dharma | sl_subscribe | table | slony _dharma | sl_table | table | slony _dharma | sl_trigger | table | slony
Nyní vytvoříme podobným způsobem stejné systémové tabulky i na druhém uzlu. Místo příkazu INIT CLUSTER použijeme příkaz STORE NODE:
STORE NODE( id = 2, COMMENT = 'Prvni slave');
Agenti
Tím jsme vytvořili potřebnou databázovou infrastrukturu a můžeme spustit agenty. Agent je program, který se předává zprávy mezi jednotlivými databázemi a zpracovává zprávy pro něj určené. Ve své činnost se podobá např. činnosti SMTP mailserveru. Pro každou databázi potřebujeme právě jednoho agenta na cluster. Pokud je databáze členem více clusterů, budete potřebovat spustit více agentů.
Replikační Agent je obsažen v programu slon. Jako parametry se mu předá jméno clusteru a potřebné informace, aby se mohl napojit do lokální databáze. Tyto informace jsou závislé na konfiguraci lokálního postgresu, který může být nastaven tak, aby autentifikoval lokální uživatele podle uid. V případě, že tomu tak není uvedeme i username a password.
%slon -d 2 dharma "dbname=slave1 host=localhost password=iehovah"
CONFIG main: local node id = 2
CONFIG main: loading current cluster configuration
CONFIG storeNode: no_id=1 no_comment='Primary Node 1'
DEBUG2 setNodeLastEvent: no_id=1 event_seq=103
DEBUG2 main: last local event sequence = 3
CONFIG main: configuration complete - starting threads
DEBUG1 localListenThread: thread starts
CONFIG enableNode: no_id=1
DEBUG1 main: running scheduler mainloop
DEBUG1 remoteWorkerThread_1: thread starts
DEBUG1 cleanupThread: thread starts
DEBUG1 syncThread: thread starts
DEBUG2 syncThread: new sl_action_seq 1 - SYNC 4
DEBUG2 localListenThread: Received event 2,4 SYNC
DEBUG2 syncThread: new sl_action_seq 1 - SYNC 5
DEBUG2 localListenThread: Received event 2,5 SYNC
Pokud agent stávkuje a nechce se spustit s výmluvou, že nad touto databází již běží, přičemž ve skutečnosti neběží, je nutné mu pomoci SQL příkazem: DELETE FROM pg_catalog.pg_listener;. Toto se stává například pokud immediate zdownujete postgesql, který během recovery databáze nemaže tuto tabulku. Vedoucí vývojového týmu PostgreSQL – Tom Lane – prohlásil, že tento bug rozhodně není jeho prioritou.
CONFIG main: local node id = 1
CONFIG main: loading current cluster configuration
CONFIG storeNode: no_id=2 no_comment='Prvni slave'
CONFIG main: configuration complete - starting threads
FATAL localListenThread: Another slon daemon is serving this node already
Terminated
Každý agent se připojí do své lokální databáze 4× a každých 10 sekund kontroluje tabulku událostí, které se následně snaží zpracovávat. Standardně jsou SYNC události generovány každých 60 sekund. Protože oba dva agenty máme v současné době připojeny pouze k jejich lokálním databázím, hromadí se nám v tabulce lokálně generované eventy, které nikdo nezpracovává. Kromě toho agent ještě provádí každých pět minut vymazání předaných eventů a po 30 minutách dokonce i s následným VACUUM.
slave1=# SELECT * from sl_event;
ev_origin | ev_seqno | ev_timestamp | ev_minxid |ev_maxxid | ev_type
-----------+----------+---------------------+ ----------+ ---------+ -------
2 | 1 | 2004-06-26 20:28:56 | 1494847 | 1494848 | SYNC
2 | 2 | 2004-06-26 20:29:56 | 1494863 | 1494864 | SYNC
2 | 3 | 2004-06-26 20:30:57 | 1494879 | 1494880 | SYNC
V dalším dílu spojíme databáze a podíváme se, jak funguje předávání zpráv prostřednictvím agentů mezi jednotlivými uzly.