
Чем больше вы погружаетесь в мир отказов, тем очевиднее становится, что очень много различных частей распределенной системы могут выйти из строя. Это верно, поскольку система становится более сложной, и все больше узлов связывается друг с другом, но это также относится и к даже меньшим системам!
Как мы узнали в первой части этой серии из двух частей о различных режимах отказа, способы, которыми наша система может выйти из строя, различаются по интенсивности. Сбой в работе не так страшен, как отказ по пропуску, а отказ по упущению не так ужасен, как сбой в результате сбоя. И, конечно же, если мы знаем способы, по которым наша система может выйти из строя, мы можем попытаться спланировать такие ситуации. Однако существуют более сложные по своей природе виды отказов; в конечном счете, это реальность любой распределенной системы, особенно очень большой.
Когда дело доходит до обработки сложных отказов, мы должны вдумчиво подумать, как мы можем их спланировать. До сих пор неудачи, которые мы рассматривали, были довольно простыми, но теперь это изменится! Давайте углубимся в несколько более сложных ошибок и попытаемся определить, что мешает им бороться.
Отвечаю на все неправильно
Что касается производительности, упущения и сбоя сбоях (все три из которых мы уже узнали), существует один общий поток: когда один узел запрашивает какой-то ответ от другого узла, ответ не приходит в надлежащее время - иногда он просто даже не появляется! Но даже если ответ приходит с опозданием, его значение все равно правильное.
Другими словами, при всех трех этих сбоях мы можем быть уверены, что, если ответ от узла действительно поступит, его содержимое будет правильным.
Однако, как мы можем себе представить, узел может доставить ответ с неправильным содержанием. Так что же тогда? Что ж, в этой ситуации мы на самом деле имеем дело с совершенно другим видом неудач; это называется отказом ответа. Ошибка ответа - это ошибка, при которой узел успешно доставляет ответ, но значение этого ответа неверно или неверно.

Для некоторых из нас отказ ответа вполне мог быть первой реальной встречей с ошибкой в распределенной системе. Например, веб-разработчики определенно видели много неудачных ответов в свое время. Если веб-разработчик напишет код с ошибками на бэкэнде, и его веб-сервер ответил неожиданным (читай: неправильным) значением для внешнего интерфейса, он увидит неожиданное значение на стороне браузера / клиента. своего кода. На самом деле, конечно же, есть ошибка в программном коде (ошибка), которая дает неожиданный результат ( ошибка), которая проявляется в ответе сервера как неправильный ответ (сбой).

Важно отметить, что сами по себе отказы реагирования бывают двух разных форм. Ответ узла может быть неверным по двум причинам. Если ответ узла неверен с точки зрения его фактического значения, мы называем это ошибкой значения.
Однако, если состояние узла при ответе неверно, мы называем это ошибкой перехода между состояниями. При таком отказе ответа мы должны быть в состоянии увидеть, что узел перешел в неправильное состояние, что обычно указывает на то, что узел каким-то образом перешел в неожиданное состояние, и что-то, вероятно, не так с логикой или управлением потоком этого узла. внутренности.
Другие узлы в распределенной системе воспринимают как сбои ответа значения, так и сбои перехода между состояниями аналогичным образом: когда они получают ответ от узла, с которым они пытаются связаться, они заметят, что ответ в чем-то неверен. В идеале, когда мы создаем распределенную систему, мы должны построить ее таким образом, чтобы мы могли учитывать потенциальные сбои; лучший способ сделать это - реализовать обработку ошибок, которая дает нашей системе способ перехватывать любые «неправильные» ответы, которые мы можем получить от узла, который выходит из строя таким образом.
В целом, с ошибками ответа не так уж сложно бороться, но мы часто можем попытаться обработать ошибки, возникающие из-за «неожиданного» ответа в узле. Более того, как многие из нас могут даже знать по опыту, работа с «неправильным» ответом означает необходимость отладки узла, на котором возникла эта ошибка. Однако, несмотря на то, что сбои в ответах раздражают, они все еще не хуже всех.
Случайные, непредсказуемые сбои
Независимо от того, выдает ли узел сбой, не отвечает, работает очень медленно или возвращает неправильный ответ, одно можно сказать наверняка - это очень хорошо, когда он постоянно дает сбой.
Отлаживать сбои и пытаться понять их намного проще, когда что-то дает сбой последовательно и одинаково.
Но бывают ситуации, когда мы даже не можем полагаться на постоянство наших неудач, что значительно усложняет их преодоление. Такие отказы известны как произвольные отказы.
Произвольные сбои - это сбои, которые происходят, когда узел отвечает разными ответами, когда части системы связываются с ним. В этом конкретном виде сбоя узел может реагировать одним способом, когда одна часть системы обращается к нему, и может реагировать совершенно иначе, когда другая часть системы пытается с ним связаться; другими словами, узел может отвечать произвольными сообщениями в совершенно произвольное время.

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

Византийские сбои, вероятно, являются самыми сложными видами сбоев в распределенных вычислениях. Фактически, византийская отказоустойчивость - это тема, которая все еще активно изучается и исследуется просто потому, что нет очевидного и однозначного ответа о том, как с этим справиться. Но что именно делает это таким трудным? Что ж, чтобы ответить на этот вопрос, нам нужно немного больше подумать о том, что неопределенность византийских сбоев и сбоев означает для остальной части нашей распределенной системы.
Недоверие
Одна из причин, по которым византийские неудачи так сложно преодолеть, заключается в том, что они сильно отличаются от других неудач, которые мы рассматривали. В отличие от сбоев производительности, пропусков и сбоев, которые являются последовательными сбоями, византийский сбой - это непоследовательный сбой. Постоянный сбой - это сбой, при котором весь принимающий «пользователь службы» - например, другой узел или служба, которая взаимодействует с какой-либо частью распределенной системы - воспринимает сбой в так же. Все пользовательские узлы службы, которые обмениваются данными с вышедшим из строя узлом, будут воспринимать одну и ту же ситуацию: все они увидят, что узел, с которым они пытаются поговорить, разбился. Таким образом, они одинаково воспринимают аварию.
Однако византийский провал - совсем другое дело; это непоследовательный сбой, когда некоторые «пользователи службы» в системе будут рассматривать ситуацию иначе, чем другие. Другими словами, поведение отказавшего узла может восприниматься в системе по-разному. Как мы можем представить, отладка, учет и обработка несогласованных отказов невероятно сложны (и, как я упоминал ранее, люди все еще исследуют и изучают такие виды отказов, чтобы попытаться бороться с этим их аспектом).
Мы более подробно рассмотрим византийские ошибки и проблемы, связанные с ними, позже в этой серии, но сейчас важно помнить, что с непоследовательными сбоями трудно справиться - не только для людей, проектирующих распределенную систему, но и для других узлов, существующих в системе.
Когда узел ведет себя непоследовательно, другие узлы в системе могут не знать, как справиться с этим несоответствием или как справиться с ним. Например, предположим, что у нас есть узел X с византийской ошибкой. Узел X может сообщить узлу A, что какое-то значение (v) равно true, но может сказать узлу B, что тот же v равен false. Теперь узлы A и B могут разговаривать друг с другом и не понимать, какое значение v на самом деле! Очевидно, оба узла A и B будут немного меньше доверять узлу X и подумают, что происходит что-то подозрительное! Люди, изучающие византийскую отказоустойчивость, пытаются придумать алгоритмы, чтобы попытаться согласовать такие противоречивые ответы.
Еще одна дополнительная сложность заключается в том, что узел X также может сообщать другим узлам в системе то, что ему известно. Например, возможно, узел A спрашивает неисправный узел X что-то об узле B. Узел X может сказать узлу A что-то истинное об узле B, или он может сказать ему что-то совершенно ложное! Это снова случай неспособности доверять тому, что говорит один узел, особенно когда он говорит неверные вещи о других узлах в системе.

Учитывая этот последний сценарий, некоторые распределенные системы также могут столкнуться с другим типом сбоя: обнаруживаемыми при проверке подлинности византийскими сбоями. Эти неудачи на самом деле являются подмножеством самих византийских неудач, но с одной оговоркой.
В случае византийских сбоев, обнаруживаемых при аутентификации, произвольные сообщения, отправленные узлом, никогда не могут быть сообщениями, которые они создают при поведении другого узла. Это означает, что, хотя узел может вести себя непоследовательно в том, как он реагирует на другие узлы, он может делать это только тогда, когда речь идет о фактах о себе и знаниях, которыми обладает сам узел. Другими словами, узел не может «лгать» о фактах о других узлах. По крайней мере, с византийскими сбоями, обнаруживаемыми при проверке подлинности, немного лучше бороться, чем с византийскими сбоями - но они ни в коем случае не просты!
Но даже в этом случае при проектировании распределенной системы мы должны учитывать все сбои (даже не самые сложные). Определение того, какие различные сбои могут возникать в системе, - это самый первый шаг к выяснению того, как их планировать и как справляться с ними, когда они происходят. Неудачи неизбежны, и в большинстве случаев они находятся вне нашего контроля. Однако то, как мы с ними справляемся, требует большей автономии.
Но это уже история для другого дня!
Ресурсы
Понимание различных способов отказа системы имеет решающее значение, если мы хотим иметь возможность. Если вы хотите продолжать изучать различные способы отказа, существует множество ресурсов; нижеприведенные, на мой взгляд, одни из лучших для начала.
- Отказоустойчивость в распределенных системах, Сумит Джайн
- Режимы отказа в распределенных системах, Альваро Видела
- Распределенные системы: отказоустойчивость, профессор Юсси Кангашарью
- Понимание отказоустойчивых распределенных систем, Флавиу Кристиан
- Типы и модели отказов, Стефан Поледна
- Отказоустойчивые системы, Ласло Бёсёрменьи