metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2016-01-25 11:00 am

Репликация таблицы БД с помощью очередей

Я тут, как обычно, подумываю, как бы заменить прямое обращение к БД из сервисов на хождение мессаг по очередям и посетила меня такая мысль: можно ли с помощью очереди, гарантирующей доставку "один раз или больше" реплицировать одну таблицу в БД, если у нее есть естественный ключ?

Мне что-то мерещится, что такая таблица является вариантом CRDT (если я воще правильно понимаю, что это такое) и можно гарантировать, что изменения с одной стороны, попавшие в очередь, дойдут до второй стороны и содержимое таблиц в конце-концов сойдется.

В случае гибели одной из БД и восстановления ее из резервной копии на какой-то момент времени, состояние рассинхронизируется и придется из второй БД принудительно передавать все данные, чтобы дозаполнить первую, или же хранить в БД полный лог изменений (заполняемый триггерами, например) и передавать изменения, начиная с момента логического времени, который видела умершая БД на момент своего резервного копирования.

Для случая нескольких таблиц со связями/FK уже так просто не получается - нужно чтобы таблицы, между которыми есть связи, реплицировались в правильном порядке - невозможно создать запись, в которой есть ссылки на другие, раньше их и удалить запись, на которую есть ссылки из других, до них невозможно.

Обычно я делаю распределенную транзакцию с двухфазной фиксацией с двумя БД и передаю данные лога транзакций и изменений между БД, пока оно работает как положено, за исключением того, что это прибивает гвоздями решение к протоколу Firebird, в котором эти распределенные транзакции предусмотрены и, например, убрать прямое обращение к БД и гонять данные по http(s) между сервисами не получается. Было бы интересно, опять же, рассмотреть вариант репликации данных между разными СУБД.

[identity profile] vromanov.livejournal.com 2016-01-25 08:05 am (UTC)(link)
Можно. Так иногда и делается. Например в TimesTen. Там пишется при изменении данных лог изменений. И он просто проигрывается на втором узле

[identity profile] plumqqz.livejournal.com 2016-01-25 08:22 am (UTC)(link)
можно ли с помощью очереди, гарантирующей доставку "один раз или больше" реплицировать одну таблицу в БД, если у нее есть естественный ключ?
Для начала надо определиться что такое "реплицировать". Если под этим подразумевается "иметь на слейве что-то подобное тому, что было некогда на мастере", то да, если иметь на слейве точную копию мастера на какой-то более ранний момент времени, то нет - сообщения в очереди не упорядочены.

Распределенные транзакции можно проводить с помощью аппликейшен серверов или в той или иной степени самодельно - начиная от атомикоса какого и заканчивая собственным кодом (там не так все сложно).

Я бы на себя взял наглость посоветовать подумать об отказе от репликации вообще в силу ее концептуальной мутности.

[identity profile] vissarion.livejournal.com 2016-01-25 08:25 am (UTC)(link)
Концепция event sourcing write-ahead log
по сути во многих бд так и происходит
в оракле по-крайней мере именно так
первым делом в журнал пишется действие еще до начала операции, журнал же реплицируется на вторую бд
(проигрыванием журнала можно однозначно восстановить состояние бд на любой момент)
а потом уже идёт собственно само действие в бд

[identity profile] juan-gandhi.livejournal.com 2016-01-25 08:32 am (UTC)(link)
А я что-то вообще на коленке с нуля раз навалял, ну очереди мессаг (вроде WAL), с трассировкой, кто что видел, идет оно по сетке, как законфигурируешь раутинг.

Собственно, речь шла об hbase, так что идеология уже присутствовала.
Edited 2016-01-25 08:33 (UTC)

[identity profile] vromanov.livejournal.com 2016-01-25 08:37 am (UTC)(link)
Есть еще такой жестокий вариант - на все таблицы навешивается триггера, которые отслеживают удаленные, добавленные и модифицированные строчки и записывают это еще в одну таблицу. Из этой таблицы идет последовательная выборка и перенос данных в другую базу. В том числе и вообще другого вида.

[identity profile] madeveloper.livejournal.com 2016-01-25 01:10 pm (UTC)(link)
CRDT подразумевает наличие что-то типа SCN в Oracle (System Change Number).
"Монотонно увеличивающегося состояния" в понимании CRDT.
Если ввести в таблицу поле аналогичное SCN, то можно легко выгребать записи изменившиеся с момента последней репликации, и так же легко отсеивать ранее учтенные обновления.
В свое время делал на подобном принципе систему синхронизации данных по накопительным картам в сети заправок.