Профиль пользователя доступен из двух регионов, и оба могут принять запись. Какой принцип маршрутизации предотвращает конкурентные изменения?
Для каждого профиля нужно назначить единственный регион-владелец записи и направлять все операции изменения туда. Остальные регионы могут обслуживать чтение, но не должны независимо принимать записи для того же профиля.
Такой принцип устраняет конкуренцию на уровне маршрутизации: в каждый момент времени существует один авторитетный поток изменений для конкретного ключа. При отказе региона владельца требуется контролируемое переключение владельца, иначе два региона могут одновременно считать себя главным.
Модель владения записью появилась как практический ответ на ограничения активно-активных распределённых систем. Размещение записи в нескольких регионах уменьшает задержку и повышает доступность, но одновременно усложняет согласование параллельных изменений.
Вместо попытки разрешать любой конфликт после записи система заранее назначает ответственный узел или регион для каждого ключа. Это переносит сложность из постоянного разрешения конфликтов в маршрутизацию и процедуру смены владельца.
Если оба региона принимают изменения одного профиля, запросы могут прибыть в разном порядке, а репликация — доставить их с задержкой или в другой последовательности. Простое правило «побеждает последняя запись» может потерять корректное изменение, особенно если часы регионов рассинхронизированы или порядок событий не совпадает со временем создания запроса.
Конфликт опасен не только потерей поля. Два региона могут независимо проверить один и тот же старый баланс, лимит или статус и принять решения, которые по отдельности выглядят допустимыми, но вместе нарушают бизнес-инвариант.
Для ключа пользователя выбирают регион-владелец. Маршрутизатор определяет владельца по стабильному ключу, например идентификатору пользователя, и перенаправляет туда все команды изменения. Географически ближайший регион при этом может обслуживать чтение из локальной реплики, если допустима задержка распространения.
Владелец должен быть однозначным и проверяемым. При смене владельца используют координацию: старый регион сначала прекращает приём записей, затем система фиксирует новую эпоху владения, после чего новый регион начинает запись. Запросы должны содержать или получать токен эпохи, чтобы старый владелец не продолжил запись после переключения.
Если запись не может быть направлена владельцу, безопаснее вернуть временную ошибку или применить контролируемую очередь, чем разрешить независимую запись в обоих регионах. Для операций, которым нужен строгий порядок, чтение перед изменением также должно учитывать состояние владельца, а не только локальную реплику.
Преимущество подхода — отсутствие большинства конфликтов и более простой порядок событий. Компромиссы — дополнительная задержка для клиента, чей профиль принадлежит удалённому региону, зависимость от маршрутизации и необходимость процедуры аварийного переключения.
Если бизнес требует записи локально в любом регионе, одного владения недостаточно. Тогда нужны явные правила слияния, версии или причинно-следственные метки, а для некоторых инвариантов — согласованный общий координатор; это сложнее и может ухудшить доступность во время сетевого разделения.
У международного сервиса профиль клиента мог изменяться через европейский и американский регионы. Сначала оба региона принимали записи, а репликация применяла изменения по мере доставки. При почти одновременной смене контактных данных один регион иногда затирал более новое значение другим.
Рассматривались три варианта. Последняя запись побеждает была простой, но могла терять обновления и зависела от корректности версий. Слияние полей уменьшало число конфликтов, но не подходило для связанных изменений и не сохраняло единый порядок бизнес-операций. Региональное владение по идентификатору клиента добавило межрегиональную задержку для части запросов, зато сделало порядок изменений однозначным.
Выбрали третий вариант, а при отказе региона применяли переключение владельца с эпохой. Локальные реплики продолжили обслуживать чтение, но команды изменения принимались только текущим владельцем. Это снизило риск конфликтов ценой контролируемой задержки при межрегиональной записи.
Нет. При сетевом разделении старый регион может не узнать о переключении и продолжить принимать записи. Поэтому смена владельца должна быть связана с эпохой, lease или другим механизмом fencing: запись со старой эпохой отклоняется хранилищем или авторитетным слоем.
Только если система предоставляет требуемую гарантию чтения. Локальная реплика может отставать, поэтому для сценария «записал — сразу прочитал» запрос направляют владельцу либо используют маркер версии, по которому реплика должна догнать нужное состояние. Иначе пользователь может увидеть устаревшие данные даже при отсутствии конфликта записей.
Нужно сначала определить, действительно ли изменения конфликтуют. Независимые поля можно разделить на отдельные логические владельцы, но для связанных бизнес-операций это часто нарушает атомарность. Если операции затрагивают общий инвариант, придётся выбрать между удалённой сериализацией через одного владельца, согласованным протоколом или явным разрешением конфликтов; универсального способа сохранить одновременно локальную запись, строгий порядок и высокую доступность нет.