Обновить

Тестирование CAP-теоремы на примере MongoDB: аварийные ситуации

Уровень сложностиСредний
Время на прочтение13 мин
Охват и читатели8.3K
Всего голосов 6: ↑6 и ↓0+8
Комментарии6

Комментарии 6

Привет, Хабр! На связи главный адвокат MongoDB Всея Руси :D

А если серьезно, спасибо за проделанную работу и статью.

Не понял насчет writeMajority и компенсирующих действий - ретрай изначального запроса тут подходит ? Или если запрос был +100 папугаев на счет господина А, а потом мажорити не набралось и клиент (как-то) понимает что нужны эти компенсирующие действия - в таком случае повторный запрос даст +200 в итоге или нет ?

Отличный вопрос, "главный адвокат"!
Компенсирующие действия клиента будут зависеть от типа запроса. Полученную от сервера ошибку нужно интерпретировать как неопределенное состояние базы данных. Поэтому, если запрос к базе данных идемпотентный, то, конечно, его можно повторить. Если же запрос опирается на данные в базе, то перед выполнением ретрая необходимо выяснить реальное состояние данных: возможно, они уже изменились на сервере, и тогда следует отказаться от ретрая, чтобы на счету не оказалось +200 попугаев.
Однако есть «подводный камень», который неочевиден: ошибка может означать, что данные были применены на primary-узле, но потенциально могут исчезнуть при неблагоприятных условиях (см. раздел «Потеря данных в наборе реплик»). Поэтому перед ретраем неидемпотентного запроса потребуется проверить согласованность данных в наборе реплик, то есть прочитать данные дважды: сначала с primary-узла (параметры {readConcern: "local", readPreference: "primary"}), а затем — данные, подтверждённые большинством узлов (параметр {readConcern: "majority"}).
Если данные различаются, то сначала нужно дождаться репликации и достижения согласованного состояния всего набора реплик. Если же данные совпали, состояние набора реплик считается согласованным, и на основе этих данных можно принимать решение о повторной отправке запроса.

Я правильно понимаю, что при выполнении запросов к MongoDB с параметрами CP, если будет риск нарушения согласованности данных (например, в момент аварии на части узлов), то произойдет ошибка, но при этом сам запрос может изменить данные в MongoDB?

Да, все верно. Ошибка - это сигнал о неопределенном состоянии данных в системе. И прежде чем продолжать работу, нужно выяснить реальное состояние и возможно дождаться достижения согласованного состояния в узлах системы.

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

  • запрос клиента может дойти до сервера БД выполниться, но ответ об успешном выполнении операции может не дойти до клиента и клиент получит ошибку timeout,

  • запрос клиента может не дойти до сервера БД, соответственно не выполниться, и клиент получит точно такую же ошибку timeout.

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

Такой настройки нет. Данные от "выпавшего" мастера не вернуть обратно в реплику, если реплика уже переизбрала другого мастера и ушла вперед.

Но если правильно установить параметры запросов и не игнорировать сообщения об ошибках, которые приходят из базы данных, то возвращать такие данные в реплику и не потребуется.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
l.tbank.ru
Дата регистрации
Дата основания
Численность
свыше 10 000 человек
Местоположение
Россия