2008-07-04

Черновик. Репликация средствами Daffodil Replicator.

Есть замечатьная задача - репликация PostgreSQL.

Описание задачи: есть куча биллинговых баз по районам. Базы крутятся на oracle 9.2.0.6 и postgresql 8.2.5 (возможно перепрыгнем на 8.3.3, но это не принципиально). Каждая база имеет свой диапазон в первичных ключах. Сделано это для обеспечения возможности слияния баз в одну большую без нарушения целостности по первичным ключам. Идет постепенная миграция с oracle на postgresql. Необходимо организовать центральный сервер в головной конторе, куда все районские базы посредством репликации будут синхронизировать данные.


После беглого рассмотрения всех существующих систем репликации для PostgreSQL (Sliny-l, bucardo, daffodil replicator, PGCluster, PyReplica, pgpool-ll) выбор для начала остановили на daffodil. По той простой причине, что он может использоваться в гетерогенной среде, написан на java, кроссплатформенный.

На данный момент существует 2 реализации daffodil - платная enterprise и бесплатная OS. Естественно, для начала пробуем OS. Качаем пакет отсюда: http://sourceforge.net/projects/daffodilreplica
На тот момент, когда качал я, последняя версия была 2.1( DaffodilReplicator2_1.zip). Ее и будем юзать.

PostgreSQL, впрочем как и Oracle крутится на серверах под управлением SLES9 и SLES10 (по массе SLES9).

Естественно, перед началом борьбы с репликацией читаем доку, которая идет в пакете и все делаем в соответствии с ней.

Перед установкой на сервер проверяем, что на нем есть java версии не меньше 1.4

root# rpm -qa | grep java
java2-1.4.2-129.14
gcc-java-3.3.3-43.41
java2-jre-1.4.2-129.14

Ну вроде как есть. Кроме того, как написано в доке, нам понадобится log4j. Качаем.

2008.07.07

Трезво поразмыслив, решил не баловаться сразу на рабочем сервере, а попробовать на своей тачке + тестовый сервер.
Первым делом мое точило - на нем будет крутиться предполагаемый районский сервер.

Используется (на OpenSUSE 10.3):
postgresql-8.2.6-0.1
postgresql-jdbc-8.1-73
java-1_5_0-sun-1.5.0_update15-0.1
log4j-1.2.12-146

Все пакеты ставились через YaST не мудрствуя лукаво.
В postgres создал схему роль test_sk, табличное пространство test_sk, базу данных UTF8_sk и в ней схему test_sk с владельцем test_sk. Залил в схему базу Скадовского РЭСа.

Содержимое архива DaffodilReplicator2_1.zip распаковал под root в папку /opt. В итоге получил каталог /opt/DaffodilReplicator2_1 в котором у нас и находится наш пока еще загадочный репликатор.

Исходя из вычитанной из официальной доки идеологии Daffodil Replicator, мой сервер, на котором находится якобы рабочая схема Скадовска, будет работать как Publisher. То есть публикует данные, которые Subscriber будет подтягивать на себя, то есть с собой синхронизировать. Так что настраиваем Publisher на моей тачке.

Под root открываем на редактирование /opt/DaffodilReplicator2_1/PubServer.sh и устанавливаем:

JAVA_HOME="/usr/lib/jvm/jre" # значение определил так: echo $JAVA_HOME
JDBC_CLASSPATH='./Replicator.jar;/usr/share/java/log4j.jar;/usr/share/pgsql/postgresql-8.2-506.jdbc3.jar' # ./Replicator уже было, /usr/share/java/log4j.jar определил так: rpm -ql log4j-1.2.12 | grep log4j.jar, /usr/share/java/log4j.jar определил так: rpm -ql postgresql-jdbc-8.1 | grep jar. Причем там есть 3 jar файла. Выбрал этот, просто потому, что нужно было что-то выбрать. Возможно, выбор неправильный, время покажет.

Теперь нужно запустить PubServer.sh. Для этого сначала даем права на выполнение (странно, что они сразу небыли установлены)

root# chmod oug+x /opt/DaffodilReplicator2_1/PubServer.sh

и запускаем Publisher

root#
/opt/DaffodilReplicator2_1/PubServer.sh

Ха, и получаем вот такую вот фигню:

USED JAVA = /usr/lib/jvm/jre
JDBC_CLASSPATH ./Replicator.jar;/usr/share/java/log4j.jar;/usr/share/pgsql/postgresql-8.2-506.jdbc3.jar
Exception in thread "main" java.lang.NoClassDefFoundError: com/daffodilwoods/repconsole/StartServer

Приплыли... Ну че, как обычно с полпинка не получилось, будем рыть...
Обана, сразу и нарыл :) Все таки google это сила. Оказывается в
JDBC_CLASSPATH вместо ";" нужно использовать ":". Исправляем:

JDBC_CLASSPATH='./Replicator.jar:/usr/share/java/log4j.jar:/usr/share/pgsql/postgresql-8.2-506.jdbc3.jar'

Запускаем

root# /opt/DaffodilReplicator2_1/PubServer.sh

И вот, о чудо, открылось какое-то окошечко. То есть я так понимаю, что пока все идет в правильном направлении. Че там дальше?
А дальше непонятно, пока. В Replicator Console Guide после запуска PubServer.sh идет описание других конфигов, про сие замечательное окно ничего нет. Так что закрываем его пока, и копаем дальше.

2008.07.08

Ну вроде стало ясно то, что в этом окне конфигуратора должна быть возможность выбрать jdbc драйвер postgres, которого в нем нет. Почему нет - непонятно. Пока займемся настройкой остальных конфигов, возможно настроив их появятся недостающие вещи...

Для начала создаем директорию /opt/DaffodilReplicator2_1/replicahome. Делаем это под root.

Беремся за редактирование /opt/DaffodilReplicator2_1/config.ini. Это основной конфигурационный файл репликатора, как я понял. Устанавливаем следующие значения параметров

REPLICATIONHOME=/opt/DaffodilReplicator2_1/replicahome
TRANSACTIONDETAIL=true # true устанавливаем для отладки. Когда пойдет в рабочую эксплуатацию, скорее всего нужно будет заменить на false, дабы не засорять логи чересчур подробной информацией по процессу репликации
TRI_Prefix=daffodil_TRI_
TRU_Prefix=daffodil_TRU_
TRD_Prefix=daffodil_TRD_
ShadowTablePrefix=daffodil_REP_SHADOW_
Seq_Prefix=daffodil_Seq_

Беремся за редактирование /opt/DaffodilReplicator2_1/log4j.properties. Это конфиг указывает, опции логирования отладочной информации. Пока трогать не будем. По умолчанию логирование выключено. Включем, если будет необходимо. Так что не редактируем этот файл.

Так. Опять запускаем PubServer.sh. Вылазит окошко "Daffodil Replicator Data Source Information..". Пробуем заполнить поля так, как нам надо. Поле "Driver" берем из доки "Replicator Console Guide", точно так же, как и поле "URL", скорректировав под нас. В итоге значение полей получаем следующее:

Driver: org.postgresql.Driver
URL: jdbc:postgresql://10.77.1.28:5432/UTF8_sk
Username: test_sk
Password: test_sk
IP address: 10.77.1.28
Server Port N...: 3001

Нажимаем кнопку "Start Server" и как всегда в первый раз получаем дулю. Вываливается окошко с ошибкой:

com.daffodilwoods.replication.RepException:
Replication-Server not started: 'FATAL: крокозяблики-квадратики "UTF8_sk" крокозяблики-квадратики'.

Обидно, что с кодировкой фигня. не прочитаешь, что написано.
Повезло, сразу разобрался что не так. Мой провтык. База называется не UTF8_sk, а UFT8_sk, что есть неправильно. Ну ошибся, когда создавал базу данных, бывает. Но исправлять выше ничего не буду, так как рабочая база будет именно UTF8_sk.

Итак, после корректировки URL открылось следующее окно. В нем создаем первую публикацию. Называем ее pub1, В поле "Conflict Resolver" оставляем значение "publisher_wins". Для репликации выбираем все таблицы. При попытке пройти дальше выкинуло окно, что ряд таблиц не имеет первичного ключа. Либо исключаем их из репликации, либо ставим первичный ключ. После того, как рапликатора предположительно удовлетворили выданные ему таблицы, появилось окошко охеренной ширины, экранов на 15-цать, где все 300 с гаком таблиц тупо перечислены в строку :) Вот такая она кривая, java, или руки у разработчиков кривые, что более вероятно... Короче, там после перечисления написано: "are having cicle in relation.Please give a relation to be suppressed". Короче, я так понял, реч идет о таблицах, которые ссылаются ключами друг на друга. Идеологию cicle таблиц я не понял, так что тупо выбираю в следующем окне все таблицы и жму OK. Сообщуха появилась еще несколько раз. Всегда выбирал все таблицы и жал OK. Дальше появляется окошко "Set Filter Clause". Фильтры никакие не нужны. Так что жмем Finish.

Блин, а так все хорошо начиналось... Вылезло окошко с ошибкой:

com.daffidilwoods.replication.RepException:
Could not publish the publication 'invalid URL or Invalid user/password.': (1)

Бл... Загадка. Роем...

В /opt/DaffodilReplicator2_1/config.ini есть несколько ненастроеных параметров. Если PubServer.sh вычитывает их при старте, то давайте попробуем настроить (когда не знаешь, откуда рыть, нужно рыть все подряд...)

VendorType=Postgres
DataBaseName=UTF8_sk
Driver=org.postgresql.Driver
Url=jdbc:postgresql://10.77.1.28:5432/UTF8_sk
UserName=test_sk
Password=test_sk

Запустив PubServer.sh видим, что я ошибся. Но настройки оставляем пока...

Попытаемся сделать максимально информативное логирование. Редактируем log4j.properties. В результате получаем:

# log4j.rootCategory=off
log4j.rootCategory=All,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %p [%c{1}] [%M %L] %m%n

Кстати, я только щас заметил, что в схеме test_sk появились таблицы вида daffodil_.... Че с ними делать если публикация не создана??? Удалить или запустить создание публикации по новой в надежде, что они будут корректными в результате таких действий??? Ну, понадеемся...

Запускаем PubServer.sh, в выпадающем списке в параметрах запомнились старые настройки, так что их можно просто выбрать. Не забываем, что таблицы типа daffodil_... в репликацию не включаем!!!

И вот, о чудо, публикация создана!!!

Теперь нужно сделать subscriber. Он у нас будет на 10.77.11.52 (SLES10 с непомнюкаким ServicePack, что для нашего кроссплатформенного daffodil никакой роли не играет). Тачка в подвале, так что, дабы не лазить туда по 10 раз в день, раскручиваем на нем vnc и работаем не вставая со стула (В Yast2 разрешаем удаленное управление, vncpasswd задаем необходимые пароли, а затем запускаем vncserver.). Распаковываем daffodil в opt, как в предыдущей установке. Проверяем, чтоб там были установлены все необходимые пакеты (postgres, jdbc драйвер, log4j, java). правда jdbc драйвер получился версии 8.1, а не 8.2, как пакеты всего остального postgres-а.

Создаем каталог /opt/DaffodilReplicator2_1/replicahome

Редактируем /opt/DaffodilReplicator2_1/SubServer.sh (предварительно дав права на выполнение на него):

JAVA_HOME="/usr/lib/jvm/java"
JDBC_CLASSPATH='./Replicator.jar:/usr/share/java/log4j-1.2.12.jar:/usr/share/pgsql/postgresql-8.1-404.jdbc3.jar'

Редактируем /opt/DaffodilReplicator2_1/config.ini

REPLICATIONHOME=/opt/DaffodilReplicator2_1/replicahome
TRI_Prefix=daffodil_TRI_
TRU_Prefix=daffodil_TRU_
TRD_Prefix=daffodil_TRD_
ShadowTablePrefix=daffodil_REP_SHADOW_
Seq_Prefix=daffodil_Seq_
TRANSACTIONDETAIL=true
VendorType=Postgres
DataBaseName=allres
Driver=org.postgresql.Driver
Url=jdbc:postgresql://10.77.11.52:5432/allres
UserName=allres
Password=allres

Обратите внимание, что вместо test_sk в subscriber используется allres - это будет общая база, куда будут лить все РЭСы. Может по моей наивности я что-то неправильно понимаю, время покажет, но мне нужно, чтоб именно так и работало.

Ну и log4j.properties делаем такой же, как и выше на publisher.

Кстати, неприятный момент - SubServer.sh кривой. Без напильника не стартанет, видать в notepad лобали. Поэтому перед запуском нужно из незакомментированных строк удалить все символы возврата каретки. Ну и после этого запускаем subscriber. не забываем при этом, что publisher уже должен быть запущен.

В первом окне запорлняем неоходимые поля так, как прописали в config.ini. В следующем делаем "Create Subscription". Поля в окне "Create Subscription" заполняем следующим образом:

Subscription Name: sub1
Publication Name: pub1
Publication Server Name: 10.77.1.28
Publication Port Number: 3001

Нажимаем "Subscribe", и как всегда получаем ошибку:

com.daffodilwoods.replication.RepEcxeption:
Error subscribing.subscription 'Connection refused to host: 127.0.0.2; nested exception is:
java.net.ConnectException: Connection refused' : {1}.

2008.07.09

Так. Разобраться не получилось, несмотря на все мои манипуляции. Пытался базу делать такую же, UFT8_sk, и еще что-то, не помню... ничего не помогло. Зато узнал вещь, о которой до этого не знал. А именно: любой адрес из подсети 127.xxx.xxx.xxx всегда пингуется. Я то наивный думал, что доступен для использования только 127.0.0.1, а оказывается вот оно как... Принципа и смысла не понял...

Короче, остановился на предположении чисто гипотетическом, что с хостом 10.77.11.52 что-то не так, например на нем 2 сетевые карты, что вызавает непонятный мне конфликт (пока предполагать больше нечего). Так что попробую подписчика развернуть на своем хосте (10.77.1.28), но на другом порту (3002)...

Так, ну ошибку насчет 127.0.0.2 я проскочил, нарвался на другую:

com.daffidilwoods.replucation.RepException:
Invalid URL or Invalid user/password.

То есть что-то все-таки не так с 10.77.11.52. Появилась еще одна версия - не тот jdbc драйвер. Щас поменяем, проверим.

Не, не помогло... Че ж с этой тварью делать??? У меня все сервера с 2-мя интегрированными сетевухами. И ни на одном нет возможности в биосе ее отключить. Если траблы из-за этого, то всё кисло... Спокойно, Ипполит, спокойно... Разворачивать назад не хочется - столько времени уже убил. Ну, короче, как всегда РЫТЬ!!!

Попробовал дать второй сетевухе IP-адрес и включить в сеть - не помогло...

2008.07.10

Варианты закончились. Попробую на другом сервере.
На другом сервере у нас SLES9 32 bit. Проставил java 1.4.2 и postgres 8.2.5, jdbc драйвера и log4j в дистре небыло, поэтому просто повыдирал jar файлы postgres с тех серверов, где тренировался, а log4j.jar выдрал из скачанного с apache.org. Все jar-ы тупо выложил в каталог /opt/jar. Вот что оказалось внутри каталога:

log4j-1.2.15.jar
postgresql-8.2-506.jdbc2.jar
postgresql-8.2-506.jdbc2ee.jar
postgresql-8.2-506.jdbc3.jar

На установленном postgres склепал роль allres, и табличное пространство, базу данных и схему с таким же именем. Права на все это хозяйство дал allres.

Конфиги daffodil настраиваем так, как делали раньше да subscriber сервера, с учетом другого ip и изменений в postgres. Листинги не привожу.

О великая, черная и необъятная ж..., неужели ты не хочешь заканчиваться...
Получил ту же ошибку с 127.0.0.2. Или у меня совсем руки кривые, или реально проблема в 2-х сетевухах...

Комментариев нет: