Итак, приступим:
Установим пакеты, необходимые для сборки skytools:
apt-get install build-essential libpq-dev postgresql-server-dev-9.2 python2.6-dev python-psycopg2 rsync
Если есть желание собрать deb-пакет (у меня было) потребуется установить ещё несколько пакетов: apt-get install devscripts autotools-dev xmlto asciidoc python-all-dev postgresql-server-dev-all libevent-dev automake libtool
Идём на сайт проекта на pgfoundry.org и качаем последний релиз: # su - postgres
~$ mkdir build && cd build
~/build$ wget http://pgfoundry.org/frs/download.php/3321/skytools-3.1.tar.gz
~/build$ tar xvf skytools-3.1.tar.gz
~/build/skytools-3.1$ cd skytools-3.1
На момент написания заметки в файле debian/rules была допущена ошибка в указании пути к pg_buildext (или я не правильно понял механизм сборки), чтобы её быстренько исправить воспользуемся sed'ом: ~/build/skytools-3.1$ sed -i 's/..debian\/pg_buildext/\/usr\/bin\/pg_buildext/' debian/rules
Но это ещё не все баги в текущем архиве, подправить нужно ещё 2 файла, иначе londiste и pgq не установятся в базу данных: ~/build/skytools-3.1$ sed -i 's/pgq.upgrade.2to3.sql/pgq.upgrade.sql/' python/pgq/cascade/admin.py
~/build/skytools-3.1$ sed -i 's/londiste.upgrade.2to3.sql/londiste.upgrade.sql/' python/londiste/setup.py
Вот теперь можно приступать к сборке deb-пакетов (разработчики skytools об этом заранее позаботились, спасибо им): ~/build/skytools-3.1$ make deb
После успешных компиляции и сборки получаем в директории на уровень выше несколько deb-пакетов: ~/build/skytools-3.1$ cd ..
~/build$ ls -1 *deb
postgresql-8.3-pgq3_3.1_i386.deb
postgresql-8.4-pgq3_3.1_i386.deb
postgresql-9.0-pgq3_3.1_i386.deb
postgresql-9.1-pgq3_3.1_i386.deb
postgresql-9.2-pgq3_3.1_i386.deb
python-pgq3_3.1_i386.deb
python-skytools3_3.1_i386.deb
skytools3_3.1_i386.deb
skytools3-ticker_3.1_i386.deb
skytools3-walmgr_3.1_i386.deb
Вуаля, теперь можно установить deb'ы (не забываем что делать это нужно от рута):
# dpkg -i *.deb
После установки компонентов skytools можно приступить настройке londiste.Архитектура работы Londiste следующая: на хосте с мастер-базой находится провайдер, который отправляет данные подписчикам, т.е. другим хостам (точнее инстансам/кластерам постгреса, которые могут выполнятся и на одном хосте). Настройку и провайдера и подписчика можно производить с одного хоста, главное чтобы с него можно было подключаться ко второй базе. В моём случае все действия производятся исключительно на мастере, но skytools должен быть установлен на обоих серверах. Установка на второй хост deb-пакетов ничем не отличается от установки на первый, за исключением того что вы можете воспользоваться уже собранными deb-пакетами ;)
Удобства ради рекомендую создать файл .pgpass с учётными данными для подключения к базам данных, формат файла предельно прост:
hostname:port:database:username:password
Любую часть можно заменить звёздочкой (*).Для начала нужно добавить londiste и pgq в нашу базу. Для этого воспользуемся утилитой qadmin, которая была добавлена в skytools3:
su - postres
~$ qadmin -h localhost -U postgres -d domains -c "install londiste"
Server version 9.2.0
INSTALL
Далее перенесём схему базы на второй сервер (на втором хосте нужно прописать соответствующие правила в pg_hba.conf): ~$ pg_dump -s -C domains | psql -h <второй_хост> -U postgres
Создадим каталоги для лог- и pid-файлов провайдера и подписчика, а затем изменим владельца этих каталогов на пользователя postgres (т.к. я запускал демонов londiste и pgq именно из-под него во время экспериментов): # mkdir -p /var/log/skytools/pgsql
# mkdir -p /var/run/skytools/pgsql
# chown postgres:postgres /var/log/skytools/pgsql
# chown postgres:postgres /var/run/skytools/pgsql
Теперь нужно создать конфигурационный файл провайдера (мастера). У меня он получился такой: ~$ cat /etc/skytools/replication_master.ini
[londiste3]
job_name = replication_src
db = host=localhost dbname=domains user=postgres
queue_name = replica
logfile = /var/log/skytools/pgsql/dns_msc.log
pidfile = /var/run/skytools/pgsql/dns_msc.pid
Далее произведём инициализацию провайдера: # su - postgres
~$ londiste3 /etc/skytools/replication_master.ini create-root master-server 'dbname=domains host=localhost'
Где master-server - это имя провайдера (мастера). Конфиг для слэйва получился почти такой же:
~$ cat /etc/skytools/dns_msc_replication_slave.ini
[londiste3]
job_name = replication_dst
db = dbname=domains host=<имя/адрес хоста мастера> user=postgres
queue_name = replica
logfile = /var/log/skytools/pgsql/dns_msc_slave.log
pidfile = /var/run/skytools/pgsql/dns_msc_slave.pid
Имя очереди (queue_name) на мастере и подписчике должно совпадать!
Подключаем потребителя (подписчика) к провайдеру (мастеру): ~$ londiste3 /etc/skytools/replication_slave.ini create-leaf slave-server 'dbname=domains host=<имя/адрес хоста мастера>' --provider='dbname=domains host=localhost'
Теперь настроим непосредственно pgq (он же ticker), ту самую очередь на которой построена репликация. Конфиг pgqd: ~$ cat /etc/skytools/pgqd.ini
[pgqd]
logfile = /var/log/skytools/pgsql/pgqd.log
pidfile = /var/run/skytools/pgsql/pgqd.pid
base_connstr = host=localhost user=postgres
initial_database = domains
Запускаем демоны londiste и pgq: postgres@master:~$ pgqd -d /etc/skytools/pgqd.ini
postgres@master:~$ londiste -d /etc/skytools/replication_master.ini worker
postgres@master:~$ londiste -d /etc/skytools/replication_slave.ini worker
Проверяем что все сервисы живы-здоровы: postgres@host1:~$ londiste3 /etc/skytools/replication_master.ini status
Queue: replica Local node: master-server
master-server (root)
| Tables: 0/0/0
| Lag: 6s, Tick: 13311
+--slave-server (leaf)
Tables: 0/0/0
Lag: 6s, Tick: 13311
postgres@host1:~$ londiste3 /etc/skytools/replication_master.ini members
Member info on master-server@replica:
node_name dead node_location
--------------- --------------- -------------------------------------------
slave-server False dbname=domains host=host2
master-server False dbname=domains host=localhost user=postgres
Радуемся тому что оно таки заработало (я был очень счастлив), но никакой репликации ещё пока не запущено :) Нужно обяснить londiste какие таблицы реплицировать, однако в моём случае не нужно было реплицировать все таблицы, более того имена таблиц у меня будут различаться:master -> slave
------------------------
domains -> domains
records_master -> records
Итак, ознакомившись в очередной раз с документацией, приступим. Сначала объясним мастеру какие таблицы будем отдавать:
postgres@host1:~$ londiste3 /etc/skytools/replication_master.ini add-table domains
postgres@host1:~$ londiste3 /etc/skytools/replication_master.ini add-table records_slave
Затем слэйву какие таблицы забирать у мастера и исправим имя принимающей таблицы: postgres@host1:~$ londiste3 /etc/skytools/replication_slave.ini add-table domains
postgres@host1:~$ londiste3 /etc/skytools/replication_slave.ini add-table records_slave --dest-table=records
Теперь нужно подождём некоторое время чтобы завершилась начальная репликация и проверим состояние: postgres@host1:~$ londiste3 /etc/skytools/replication_master.ini status
Queue: replica Local node: master-server
master-server (root)
| Tables: 2/0/0
| Lag: 3s, Tick: 13326
+--slave-server (leaf)
Tables: 2/0/0
Lag: 3s, Tick: 13326
Одинаковые строчки "Tables: 2/0/0" говорят о том что всё пучком. Если нет, то идём в документацию и узнаём что же означают эти цифры x/y/z:- x - количество таблиц в состоянии ok (replicated), если на мастере - то они нормально отдаются слэйвам, если на слэйве - нормально прилетают с мастера;
- y - количество таблиц в состоянии half (initial copy not finnished), у мастера должно быть 0, у промежуточного в каскадной репликации и слэйва - указывает количество таблиц в процессе копирования
- z - количество таблиц в состоянии ignored (table not replicated locally), у мастера 0, у слэйва - количество таблиц, которые не добавлены для репликации с мастера (т.е. мастер отдает, а слэйв их просто не забирает)
Возможные грабли:
- Ошибка "OperationalError: could not access file "$libdir/pgq_lowlevel": No such file or directory" - не установлен пакет postgresql-x.x-pgq3_3.1_i386.deb, возможно он даже не собрался, проверьте что собрались все deb'ы. У меня они не собирались как раз из-за неправильного пути к pg_buildext
- ERROR Job <имя задачи из конфига> crashed: File not found: pgq.upgrade.2to3.sql - не исправлен pgq/cascade/admin.py как указано ввыше
Если есть какие-либо вопросы или что-то не получается - спрашивайте в комментариях.
Доброго дня!
ОтветитьУдалитьС подобной ошибклй не сталкивались?
londiste3 /etc/skytools/londiste-master.ini create-root host0 'dbname=testdb host=host0'
2015-08-13 23:46:37,444 2228 INFO plpgsql is installed
2015-08-13 23:46:37,447 2228 INFO pgq is installed
2015-08-13 23:46:37,450 2228 INFO Installing pgq.get_batch_cursor
2015-08-13 23:46:37,452 2228 INFO Reading from /usr/share/skytools3/pgq.upgrade.2to3.sql
2015-08-13 23:46:37,483 2228 ERROR Job postgres_rep got error on connection 'db': column "queue_disable_insert" of relation "queue" already exists. Query: alter table pgq.queue add column queue_disable_insert boolean;
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/skytools/scripting.py", line 568, in run_func_safely
return func()
File "/usr/lib/python2.7/site-packages/skytools/adminscript.py", line 62, in work
fn(*cmdargs)
File "/usr/lib/python2.7/site-packages/pgq/cascade/admin.py", line 147, in cmd_create_root
return self.create_node('root', args)
File "/usr/lib/python2.7/site-packages/pgq/cascade/admin.py", line 198, in create_node
self.install_code(db)
File "/usr/lib/python2.7/site-packages/londiste/setup.py", line 29, in install_code
CascadeAdmin.install_code(self, db)
File "/usr/lib/python2.7/site-packages/pgq/cascade/admin.py", line 425, in install_code
skytools.db_install(db.cursor(), objs, self.log)
File "/usr/lib/python2.7/site-packages/skytools/sqltools.py", line 531, in db_install
obj.create(curs, log)
File "/usr/lib/python2.7/site-packages/skytools/sqltools.py", line 490, in create
curs.execute(stmt)
File "/usr/lib/python2.7/site-packages/psycopg2/extras.py", line 120, in execute
return super(DictCursor, self).execute(query, vars)
ProgrammingError: column "queue_disable_insert" of relation "queue" already exists
!? :( Как бы это победить?
а у меня вот такая ошибка в логе слэйва:
ОтветитьУдалить2015-08-18 11:39:13,529 17409 ERROR Job slave01_account_l3 got error on connection '_provider_db': schema "pgs_distribution_metadata" does not exist. Query:
SELECT n.nspname||'.'||c.relname AS name
...
Traceback (most recent call last):
File "/usr/lib64/python2.6/site-packages/skytools/scripting.py", line 568, in run_func_safely
return func()
File "/usr/lib64/python2.6/site-packages/londiste/table_copy.py", line 229, in work
return Replicator.work(self)
File "/usr/lib64/python2.6/site-packages/pgq/cascade/consumer.py", line 199, in work
return BaseConsumer.work(self)
File "/usr/lib64/python2.6/site-packages/pgq/baseconsumer.py", line 257, in work
self._launch_process_batch(db, batch_id, ev_list)
File "/usr/lib64/python2.6/site-packages/pgq/baseconsumer.py", line 286, in _launch_process_batch
self.process_batch(db, batch_id, list)
File "/usr/lib64/python2.6/site-packages/pgq/cascade/consumer.py", line 172, in process_batch
self.process_remote_batch(src_db, tick_id, event_list, dst_db)
File "/usr/lib64/python2.6/site-packages/londiste/playback.py", line 377, in process_remote_batch
self.sync_tables(src_db, dst_db)
File "/usr/lib64/python2.6/site-packages/londiste/playback.py", line 433, in sync_tables
res = self.sync_from_copy_thread(cnt, src_db, dst_db)
File "/usr/lib64/python2.6/site-packages/londiste/playback.py", line 585, in sync_from_copy_thread
self.do_copy(t, src_db, dst_db)
File "/usr/lib64/python2.6/site-packages/londiste/table_copy.py", line 165, in do_copy
stats = p.real_copy(src_real_table, src_curs, dst_curs, common_cols)
File "/usr/lib64/python2.6/site-packages/londiste/handler.py", line 238, in real_copy
write_hook = _write_hook)
File "/usr/lib64/python2.6/site-packages/skytools/sqltools.py", line 446, in full_copy
src_curs.copy_expert(sql_to, buf)
ProgrammingError: schema "pgs_distribution_metadata" does not exist
Разобрался. Теперь все работает. Надо было включить extension pg_shard.
ОтветитьУдалитьВопрос такой - на таблице-приемнике висит другой триггер на BEFORE INSERT, и он почему-то не срабатывает...какие могут быть варианты?
ОтветитьУдалить