avlasov (avlasov) wrote,
avlasov
avlasov

Category:

Мини-учебнег по распределенным системам/протоколам. Восстановление после сбоев, ч.2

Продолжим восстанавливаться после сбоев. В предыдущей части мы рассмотрели то, что происходит на границах системы: при получении сообщений извне и отправки их наружу. А также восстановление после сбоев с точки зрения каналов общения с внешним миров. Это очень важные моменты, ведь какое состояние нужно хранить в персистентном хранилище - и восстанавливать после сбоев, зависит от того, какую мы инфу выдали во внешний мир. А само состояние (во многом) определяется тем, какие события мы получили из внешнего мира. Основная мораль: прежде чем отправить инфу, нужно убедиться, что при сбое, мы эту инфу не "забудем". Эта формулировка простая, а вот более заумная: - то, состояние, что будет после восстановления после сбоя, будет консистентным с той картиной мира, которую мы сформировали у внешнего наблюдателя.

Пример, мы послали ордер на биржу, произошел сбой, и так как биржа (внешний наблюдатель) получила ордер, то при восстановлении состояния, хорошо бы чтобы этот ордер тоже восстановился. Делать мы это можем разными способами, но основной - записать инфу об этом ордере в свое хранилище. И важный момент - мы задерживаем отправку событий во внешний мир, до тех пор пока не получим подтверждение, что вся нужная для восстановления инфа помещена в персистентной хранилище. Это мы называем output commit. Рассмотрим теперь вопрос, что это за инфа, которую нужно поместить.

Я ранее делал различие между текущим состоянием системы и состоянием, которое будет восстановлено после сбоя, ибо это понятно разные вещи. Но вообще говоря мы можем в процессе output commit'а записать текущее состояние системы в персистентное хранилище. Конечно это редко когда приемлимо, ибо может быть долго и может потребовать приостановки обработки запросов. Особенно это заморочно в распределенной системе.

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

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

Рассмотрим еще такой аспект: если мы делаем инкрементальный снэпшот сложного состояния, например, распределенного по разным нодам, то мы этот инкремент можем разбить на части, так сказать "горизонтально": например, на куски состояний, находящихся на разных нодах. Состояние на каждой ноде мы тоже можем так или иначе поделить на части, например, в зависимости от степени "параллелизма" по данным (мы можем обрабатывать события в рамках какого-то домена независимо от событий в другом домене, например, обработка событий для одного клиента не зависит от обработки событий для другого клиента - multi-tenant). Т.е. инкременты снэпшотов мы так же можем делать по частям. Что в частности, актуально для восстановления после сбоев: у нас скорее всего сдохла не вся система, а только отдельные ноды, т.е. и восстановить нам надо кусок инкремента(ов).

Таким образом, хотя задача установления полного порядка среди событий в системе слишком сложная, на практике, мы можем избежать этой проблемы, воспользуясь особенностями системы. В частности, мы можем обнаружить немало участков, где события обрабатываются независимо друг от друга. А значит нам и не требуется полный порядок среди событий. Но посвятим этой теме отдельный пост (или даже несколько).
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 0 comments