Классика баз данных - статьи

       

Репликация


Поддержка репликации в базах данных OLTP преследует несколько целей. Во-первых, наличие нескольких реплик базы данных способствует повышению уровня доступности, поскольку транзакции могут продолжать выполняться даже при выходе из строя части узлов системы, содержащих реплики. Кроме того, упрощается восстановление работоспособности отказавших серверов, поскольку для этого нужно всего лишь скопировать состояние какой-либо реплики, а не воссоздавать состояние отказавшего сервера на основе журналов [16]. Наконец, запросы только на чтение могут выполняться в любом узле, содержащем реплику, без потребности во взаимодействии с другими репликами, так что репликация может привести к значичительному повышению производительности при наличии высоких рабочих нагрузок, которые, в основном, включают операции чтения.

Последствием использования недетерминированных протоколов управления параллелизмом является то, что два сервера с идентичным программным обеспечением управления базами данных и одним и тем же исходным состоянием баз данных при получении одинаковых последовательностей запросов на образование транзакции могут перевести свои базы данных в совершенно разные состояния. В схемах репликации обычно предусматриваются предосторожности, предотвращающие или ограничивающие такие расхождения. Желательно, чтобы схема репликации отвечала трем следующим требованиям:

  • согласованность реплик;

  • корректность всех реплик;

  • низкие накладные расходы.

Поскольку в современных системах баз данных допускается недетерминированное поведение, схемы репликации обычно основываются на компромиссе между согласованностью, корректностью и низкими накладными расходами. Распространенные схемы репликации обычно относятся к одному из следующих трех семейств, различаясь деталями и стоимостью:

  • Репликация после записи (post-write replication). Здесь записи сначала выполняются над одной репликой, а репликация происходит после завершения записей. К этой категории относится традиционная репликация "ведущий-подчиненный" (master-slave), где все транзакции выполняются основной "ведущей" системой, наборы записи (write set) которой затем передаются во все "подчиненные" системы с репликами, обновляющие данные в том же порядке, чтобы обеспечить сближение своего результирующего состояния с состоянием базы данных ведущей системы.
    Обычно это реализуется на основе "пересылки журнала" (log shipping) [14, 20] – ведущая система рассылает журнал транзакций, который воспроизводится подчиненными системами над каждой репликой.

    Эта категория также включает схемы, в которых для разных элементов данных имеются разные ведущие системы, а также вариации на эту тему, в которых разные узлы могут получать "арендные договора" ("lease"), делающие их ведущими для некоторого конкретного элемента данных. В этих случаях при обработке транзакций, которые затрагивают данные более чем одной ведущей системы, требуется некоторый сетевой коммуникационный протокол (например, протокол двухфазной фиксации), обеспечивающий согласованность реплик. Если используются протоколы управления параллелизмом, основанные на блокировках, то необходимо еще и выявлять распределенные тупиковые ситуации.

    При применении и традиционной схемы репликации "ведущий-подчиненный", и ее вариантов, когда для разных данных ведущими являются разные узлы, записи сначала выполняются в ведущем узле, и данные реплицируются после их завершения. Уровень отставания реплик от основных данных зависит от скорости, с которой подчиненные узлы применяют наборы записи ведущего узла, но всегда имеется хотя бы незначительное отставание. Поэтому не гарантируется, что в ответ на запросы по чтению, направляемые в подчиненные узлы, будут выдаваться "свежие" результаты, если только не заставлять приложения ждать, пока подчиненные узлы "не наверстают упущенное" (для некоторых приложений это допустимо) [22. 19, 2].

    Кроме того, в системах с репликацией после записи имеется фундаментальная взаимозависимость между величиной задержки, долговечностью (durability) транзакций и согласованностью реплик. Если ведущий узел не фиксирует транзакции до получения подтверждения о получении подчиненными узлами пересланных им данных, то возрастает задержка. В противном случае, если в ведущем узле возникает отказ, журнальные записи, переданные перед этим в подчиненные узлы, могут до них не дойти.


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



  • Активная репликация с использованием синхронизированных блокировок (active replication with synchronized locking). В этом случае все узлы, содержащие реплики, должны договориться о блокировках по записи, которые должны накладываться на элементы данных [4]. Поскольку записи могут происходить только при наличии согласованной монопольной блокировки, во всех узлах, содержащих реплики, обновления будут происходить некоторым образом, эквивалентным такому же последовательному порядку, что гарантирует согласованность реплик. Недостатком этой схемы является дополнительная задержка, вызываемая сетевыми комуникациями для обеспечения синхронизации на основе блокировок. По этой причине такая схема на практике используется намного реже схем с репликацией после записи.


  • Репликация с отложенной синхронизацией (replication with lazy synchronization). Транзакции выполняются независимо в нескольких активных узлах, содержащих реплики (которые, возможно, временно рассогласуются), а позже их состояния синхронизуются [10, 7, 17]. Схемы с отложенной синхронизацией обеспечивают хорошую производительность за счет (временной) утраты согласованности реплик.


Если бы система баз данных могла выполнять последовательности поступающих транзакций полностью детерминированным образом, то можно было бы полностью избежать компромиссов между описанными выше желательными свойствами. Транзакции можно было бы заранее упорядочивать на некотором центральном сервере (или путем использования некоторой распределенной службы [18, 24]), а затем направлять их пакетами в каждый узел, содержащий реплики, для детерминированного выполнения. Это будет гарантировать, что в каждом из этих узлов результирующее состояние реплики будет согласовано с состояниями всех других реплик, и не потребуются накладные расходы для достижения каких-либо дополнительных соглашений или синхронизации.


Содержание раздела