Для этого есть концептуальная причина. Система представляется клиенту в виде черного ящика. Вся идея этого бокса состоит в том, чтобы обеспечить надежный доступ к некоторому сервису, таким образом, он должен маскировать сбои конкретной реплики. В противном случае, если вы отбрасываете все при каждом изменении представления, клиенты будут постоянно терять свои данные. По сути, ваше решение просто противоречит спецификации. Фаза фиксации нужна именно для предотвращения подобных ситуаций. Если запрос принимается только при наличии 2f + 1 сообщений COMMIT, то, даже если все f реплики неисправны, оставшиеся узлы могут восстановить все зафиксированные запросы, это обеспечивает надежный доступ к системе.
Есть еще и техническая причина. Теоретически система является асинхронной, это означает, что вы даже не можете гарантировать, что изменение представления произойдет только в результате сбоя. Некоторые реплики могут только подозревать, что лидер неисправен, и менять вид. С вашим решением возможно, что система отбросит все, что было принято, даже если ни одна из реплик не является неисправной.
Если вы новичок в распределенных системах, я предлагаю вам взглянуть на классические протоколы, допускающие невизантийские сбои (например, Paxos), они проще, но решают проблемы аналогичным образом.
Редактировать
Когда я говорю, что клиенты постоянно теряют свои данные, это немного больше, чем кажется. Я говорю о влиянии конкретного клиентского запроса на систему. Возьмем хранилище "ключ-значение". Клинет A
связывает некоторые value
с некоторыми key
через наш черный ящик. Черный ящик теперь упорядочивает этот запрос по отношению к любым другим параллельным (или просто параллельным) запросам. Затем он реплицирует его на все реплики и, наконец, уведомляет A
. Без фазы фиксации нет упорядочивания, и в двух разных представлениях наш черный ящик может выбрать два разных порядка выполнения клиентских запросов. При этом возможно следующее:
- одновременно
t
, A
связывает value
с key
, и поле одобряет это,
- в то время
t+1
, B
связывает value_2
с key
, и поле одобряет это,
- в то время
t+2
, C
читает value_2
из key
,
- просмотреть изменение (невидимо для клиентов),
- в то время
t+3
, D
читает value
с key
.
Обратите внимание, что (5) возможно не потому, что ящик не знает value_2
(как вы упомянули, само значение может быть повторно отправлено), а потому, что он не знает, что ранее он сначала записал value
, а затем перезаписал его с помощью value_2
. В новом представлении системе нужно как-то упорядочить эти два запроса, но не повезло, решение не согласуется с прошлым.
Возможная синхронизация - это способ гарантировать работоспособность протоколов, однако она не может предотвратить ситуации, описанные выше. В конечном итоге синхронизация означает, что в конечном итоге ваша система будет вести себя так же, как синхронная, но вы не знаете, когда до этого времени могут произойти какие-либо странные вещи. Если в течение асинхронного периода нарушается свойство безопасности, то очевидно, что вся система небезопасна.
person
vonaka
schedule
22.07.2020