Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
440-620.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
4.13 Mб
Скачать

7.6.3. Протоколирование сообщений

Мы пришли к выводу, что создание контрольных точек — довольно затратная операция, особенно если учесть необходимость записи состояния в устойчивое хранилище. Поэтому следует применять технологии сокращения числа кон­трольных точек, не ухудшающие качества исправления ошибок. Одна из важней­ших технологий такого типа в распределенных системах — это протоколирование сообщений (message logging).

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

Этот способ хорошо работает при соблюдении условий так называемой кусоч­но детерминированной модели (piecewise deterministic model). Согласно этой моде­ли считается, что выполнение каждого процесса разбивается на последователь­ность интервалов, во время которых происходят события. Это те же события, которые мы обсуждали в главе 5 в контексте отношения «происходят раньше» по Лампорту. Так, например, событием может быть выполнение инструкции, от­правка сообщения и т. п. Каждый интервал в кусочно детерминированной мо­дели считается начинающимся с недетерминированного события, такого как по­лучение сообщения. Однако с этого момента выполнение процесса полностью детерминировано. Концом интервала считается последнее событие из цепочки детерминированных перед новым недетерминированным событием.

В результате интервал можно повторить с известным результатом, то есть аб­солютно детерминированным образом, начиная с повторения того же самого не­детерминированного события. Соответственно, если мы запишем в журнал все недетерминированные события модели, то получим возможность полностью, де­терминированным образом повторить все выполнение процесса.

Если полагать, что журнал сообщений при аварии процесса необходимо вос­становить для восстановления глобально непротиворечивого состояния, то для нас важно точно знать время записи сообщений в журнал. В соответствии с под­ходом, описанным в [10], обнаруживается, что можно легко характеризовать множество схем протоколирования сообщений, сосредоточившись на том, как они работают с процессами-сиротами.

Осиротевший процесс (orphan process) — это процесс, состояние которого про­тиворечит состоянию другого, сначала отказавшего, а затем восстановленного про­цесса. В качестве примера рассмотрим ситуацию, представленную на рис. 7.18. Процесс Q получает от процессов Р и R сообщения т1 ит2 соответственно, после чего посылает сообщение тЗ процессу R. Однако в отличие от других сообщений сообщение т2 в журнал не записывается. Если происходит отказ процесса Q, для его восстановления задействуются только записанные в журнал сообщения, в на­шем примере — т1. Поскольку сообщение т2 не сохранено в журнале, его пере­дача не будет воспроизведена, а значит, передачи сообщения тЗ также не про­изойдет, что и показано на рисунке.

Отказ от восстановления процесса Q

Рис. 7.18. Неправильное воспроизведение сообщений после восстановления ведет к появлению осиротевших процессов

Таким образом, ситуация после восстановления процесса Q противоречит си­туации до его восстановления. Так, в частности, процесс R хранит сообщение (тЗ), которое было передано перед отказом, но получения и доставки которого при воспроизведении событий, имевших место перед сбоем, не происходит. По­нятно, что такого противоречия нужно избегать.

Характеристические схемы протоколирования сообщений

Чтобы характеризовать различные схемы протоколирования сообщений, мы ис­пользуем подход, описанный в [10]. Предполагается, что каждое сообщение т имеет заголовок, содержащий всю информацию, необходимую для повторной пе­редачи этого сообщения и правильной его обработки. Так, например, каждый за­головок определяет отправителя и получателя, а также последовательный номер для распознавания дубликатов. Кроме того, к заголовку может добавляться вхо­дящий номер, чтобы точно определить момент обработки сообщения получив­шим его приложением.

Сообщение называется устойчивым (stable), если оно не может быть потеря­но, например, после записи в устойчивое хранилище. Устойчивые сообщения могут использоваться для восстановления путем воспроизведения их передачи.

Каждое сообщение т отвечает за набор процессов DEP(m), которые зависят от доставки т. В частности, DEP(m) состоит из тех процессов, которым должно прийти это сообщение. Кроме того, если другое сообщение, т', причинно завися­щее от доставки т, доставляется процессу Q, то Q также входит в набор DEP(m). Отметим, что причинная зависимость т' от доставки т означает, что оно посы­лается тем же самым процессом, который ранее получил т или другое сообще­ние, причинно зависящее от доставки т.

Набор COPY(m) состоит из тех процессов, которые содержат копию т, но (пока) не в своих локальных хранилищах. Когда процесс Q получает сообщение т, он также становится членом COPY(m). Отметим, что COPY(m) состоит из тех процессов, которые могут передавать копию т для воспроизведения передачи. Если все эти процессы отказали, очевидно, что воспроизведение передачи т ока­зывается невозможным.

Используя эту нотацию, легко определить, что же такое осиротевший про­цесс. Предположим, что в распределенной системе отказали несколько процес­сов. Пусть Q — один из сохранившихся процессов. Процесс Q является сиротой, если существует такое сообщение т, что Q оказывается в наборе DEP(m)} в то время как все процессы из COPY(m) отказали. Другими словами, осиротевший процесс появляется в том случае, если он зависит от сообщения т} однако нет никакой возможности повторить передачу этого сообщения.

Чтобы предотвратить появление осиротевших процессов, необходимо гаран­тировать, что в DEP(m) не будет выживших процессов, если откажут все процес­сы в COPY(m). Система оказывается в таком состояние, если каждый процесс, являющийся членом набора DEP(m), также является и членом набора COPY(m). Другими словами, всякий процесс, зависящий от доставки сообщения т> должен хранить копию этого сообщения.

Существует два основных подхода, которым мы можем следовать. Первый из них представлен так называемыми протоколами пессимистического протоколи­рования (pessimistic logging protocols). В этих протоколах предполагается, что для каждого неустойчивого сообщения т имеется хотя бы один зависящий от него процесс. Другими словами, протоколы пессимистического протоколирования предполагают, что любое неустойчивое сообщение т доставляется как минимум в один процесс. Отметим, что как только т доставляется, скажем, в процесс Р, этот процесс становится членом набора COPY(m).

Самое плохое, что может произойти, — процесс Р откажет еще до того, как бу­дет записано сообщение т. В случае пессимистического протоколирования про­цессу Р после получения сообщения т нельзя рассылать какие-либо сообщения, пока т не будет записано в устойчивое хранилище. Таким образом, пока не будет гарантирована возможность повторной посылки сообщения т, не сможет поя­виться ни одного процесса, зависящего от доставки т процессу Р. Таким обра­зом, мы полностью предотвращаем появление осиротевших процессов.

В противоположность этому в протоколе оптимистического протоколирова­ния (optimistic logging protocol) реальная работа начинается после отказа процес­са. В частности, допустим, что для некоторого сообщения т отказали все процес­сы из набора COPY(m). Согласно оптимистическому подходу любой осиротевший процесс из DEP(m) откатывается в такое состояние, когда он перестает входить в набор DEP(m).Как было указано в [137], пессимистическое протоколирование значительно проще оптимистического, так что этот способ протоколирования сообщений при практической разработке распределенных систем предпочтительнее.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]