Репликация таблицы БД с помощью очередей
Я тут, как обычно, подумываю, как бы заменить прямое обращение к БД из сервисов на хождение мессаг по очередям и посетила меня такая мысль: можно ли с помощью очереди, гарантирующей доставку "один раз или больше" реплицировать одну таблицу в БД, если у нее есть естественный ключ?
Мне что-то мерещится, что такая таблица является вариантом CRDT (если я воще правильно понимаю, что это такое) и можно гарантировать, что изменения с одной стороны, попавшие в очередь, дойдут до второй стороны и содержимое таблиц в конце-концов сойдется.
В случае гибели одной из БД и восстановления ее из резервной копии на какой-то момент времени, состояние рассинхронизируется и придется из второй БД принудительно передавать все данные, чтобы дозаполнить первую, или же хранить в БД полный лог изменений (заполняемый триггерами, например) и передавать изменения, начиная с момента логического времени, который видела умершая БД на момент своего резервного копирования.
Для случая нескольких таблиц со связями/FK уже так просто не получается - нужно чтобы таблицы, между которыми есть связи, реплицировались в правильном порядке - невозможно создать запись, в которой есть ссылки на другие, раньше их и удалить запись, на которую есть ссылки из других, до них невозможно.
Обычно я делаю распределенную транзакцию с двухфазной фиксацией с двумя БД и передаю данные лога транзакций и изменений между БД, пока оно работает как положено, за исключением того, что это прибивает гвоздями решение к протоколу Firebird, в котором эти распределенные транзакции предусмотрены и, например, убрать прямое обращение к БД и гонять данные по http(s) между сервисами не получается. Было бы интересно, опять же, рассмотреть вариант репликации данных между разными СУБД.
Мне что-то мерещится, что такая таблица является вариантом CRDT (если я воще правильно понимаю, что это такое) и можно гарантировать, что изменения с одной стороны, попавшие в очередь, дойдут до второй стороны и содержимое таблиц в конце-концов сойдется.
В случае гибели одной из БД и восстановления ее из резервной копии на какой-то момент времени, состояние рассинхронизируется и придется из второй БД принудительно передавать все данные, чтобы дозаполнить первую, или же хранить в БД полный лог изменений (заполняемый триггерами, например) и передавать изменения, начиная с момента логического времени, который видела умершая БД на момент своего резервного копирования.
Для случая нескольких таблиц со связями/FK уже так просто не получается - нужно чтобы таблицы, между которыми есть связи, реплицировались в правильном порядке - невозможно создать запись, в которой есть ссылки на другие, раньше их и удалить запись, на которую есть ссылки из других, до них невозможно.
Обычно я делаю распределенную транзакцию с двухфазной фиксацией с двумя БД и передаю данные лога транзакций и изменений между БД, пока оно работает как положено, за исключением того, что это прибивает гвоздями решение к протоколу Firebird, в котором эти распределенные транзакции предусмотрены и, например, убрать прямое обращение к БД и гонять данные по http(s) между сервисами не получается. Было бы интересно, опять же, рассмотреть вариант репликации данных между разными СУБД.
no subject
no subject
Для начала надо определиться что такое "реплицировать". Если под этим подразумевается "иметь на слейве что-то подобное тому, что было некогда на мастере", то да, если иметь на слейве точную копию мастера на какой-то более ранний момент времени, то нет - сообщения в очереди не упорядочены.
Распределенные транзакции можно проводить с помощью аппликейшен серверов или в той или иной степени самодельно - начиная от атомикоса какого и заканчивая собственным кодом (там не так все сложно).
Я бы на себя взял наглость посоветовать подумать об отказе от репликации вообще в силу ее концептуальной мутности.
no subject
no subject
no subject
no subject
no subject
no subject
Не могу не обратить внимание на то, что нельзя забывать, что на слейве можно увидеть базу в таком состоянии, в каком ее нельзя увидеть на мастере (хотя к собственно очередям это отношения не имеет).
no subject
Для нескольких связанных таблиц можно даже не пытаться, бесполезно.
Кстати, а разве при групповом коммите ставится одинаковый логический таймстамп? Я думал, он там монотонно возрастающий.
no subject
no subject
В случае группового коммита ж это совсем не обязательно так!
Скажем, они выполнились последовательно, но записались одной транзакцией.
Чиста для технической экономии и оптимизации на этом.
no subject
Чиста для технической экономии и оптимизации на этом.
Если они пришли к коммиту вместе, то, стало быть, ни одна из них не ждала блокировок другой. Если так, он неважен порядок, в котором они выполняются - некоторая последовательность, полная параллельность или какая-то комбинация.
no subject
no subject
no subject
no subject
типа в каждой транзакции берём скрипт для выполнения и кладём его в таблицу аудита
а второе приложение эту таблицу читает и выполняет скрипты на другой базе
no subject
no subject
no subject
no subject
no subject
no subject
Это не моя фантазия. Это именно пример работающей системы построенной на базе очереди
no subject
no subject
no subject
по сути во многих бд так и происходит
в оракле по-крайней мере именно так
первым делом в журнал пишется действие еще до начала операции, журнал же реплицируется на вторую бд
(проигрыванием журнала можно однозначно восстановить состояние бд на любой момент)
а потом уже идёт собственно само действие в бд
no subject
Собственно, речь шла об hbase, так что идеология уже присутствовала.
no subject
no subject
no subject
no subject
no subject
"Монотонно увеличивающегося состояния" в понимании CRDT.
Если ввести в таблицу поле аналогичное SCN, то можно легко выгребать записи изменившиеся с момента последней репликации, и так же легко отсеивать ранее учтенные обновления.
В свое время делал на подобном принципе систему синхронизации данных по накопительным картам в сети заправок.
no subject