Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Создание интернет-магазина от 350 руб!
Большой выбор шаблонов. Поддержка 24/7. Месяц бесплатно!
2010 г.

Дом на песке

Пэт Хелланд, Дейв Кэмпбел
Перевод: Сергей Кузнецов

Назад Содержание Вперёд

6. Дзэн и искусство согласованности "рано или поздно"4

В этом разделе мы более глубоко рассмотрим понятие согласованности "рано или поздно" и обсудим, как можно создавать поддерживающие такую согласованность приложения. Мы начнем с пары примеров: системы хранения компании Amazon Dynamo и основанного на ней приложение Shopping Cart и классического банковского приложения клиринга чеков. Затем мы поговорим о приложениях, реализующих согласованность "рано или поздно", и сопоставим это с трудностями обеспечения согласованности этого вида на уровне хранения данных. Наконец, мы обсудим важность "операционно-центрического" ("operation-centric") подхода к обеспечению согласованности "рано или поздно", при применении которого операции, требуемые пользователю, регистрируются и становятся основой реализации согласованности "рано или поздно".

6.1 Пример 4: Shopping Cart и Dynamo

Система хранения данных Dynamo [18] используется для поддержки корзин покупок и других систем компании Amazon. Dynamo – это реплицированное хранилище BLOB'ов, реализованное с применением динамической таблицы хэширования (Dynamic Hash Table, DHT). Dynamo представляет интерес во многих отношениях, включая сознательный выбор поддержки доступности в ущерб согласованности. Dynamo всегда принимает операции PUT, даже если это приведет к получению более поздними операциями GET несогласованных данных.

В [18] взаимодействие приложений с системой Dynamo основывается на интерфейсе PUT и GET. Из-за аномалий репликации операция GET может возвращать устаревшую информацию. Выполнение операции PUT над этой устаревшей информацией может приводить к образованию параллельных версий. Более поздняя операция GET над тем же BLOB'ом может вернуть две версии, происходящие от одной и той же версии BLOB'а, или две "двоюродные" версии, и приложение Shopping Cart должно их согласовать. Система Dynamo, действующая, как основа хранения данных, может возвращать в ответ на GET две или большее число старых версий. Последующая операция PUT должна записать версию того же BLOB'а, в которой интегрируются и согласовываются все предыдущие версии.

Для обеспечения возможности интеграции версий на уровне приложения Shopping Cart должно регистрировать операции наподобие того, как это делается в бухгалтерской книге. Операция удаления из корзины некоторого товара регистрируется как операция добавления к корзине. Эти операции "ADD-TO-CART", "CHANGE-NUMBER" и "DELETE-FROM-CART" обычно можно согласовать, когда они, в конце концов, собираются вместе. Очень редкие аномалии в Shopping Cart являются приемлемыми, поскольку заказ посетителя магазина проверяется в течение процедуры его оформления. Недоступность услуги корзины покупок обходилась бы Amazon очень дорого, поскольку это приводило бы к упадку бизнеса и неудовлетворенности пользователей.

Dynamo является основой хранения данной, независимой от приложения Shopping Cart, которое на нем базируется. В ответ на операцию GET Dynamo возвращает некоторый BLOB (а иногда два или большее число BLOB'ов). Если возвращается более одного BLOB'а, приложение должно согласовать версии И записать результат при помощи следущей операции для той же корзины. Приложение Shopping Cart может это сделать за счет представления содержимого корзины в виде набора операций. Уникально идентифицируемые операции над покупками можно объединить в список с предсказуемым результатом. Это является ключом к коммутативности операций над корзиной покупок. В свою очередь, коммутативность используется для достижения исключительно высокого уровня доступности.

6.2 Пример 5: банковские счета и книги счетов

Имеются основания для наличия на чеках контрольных номеров. Контрольный номер (в сочетании с идентификатором банка и номером счета) обеспечивает уникальный идентификатор. За исключением ошибочных ситуаций (и/или случаев мошеничества) получатель средств по данному чеку и сумма этих средств являются неизменными. Чек поступает в банковскую систему с известным уникальным идентификатором, и участники слабо связанного процесса совместно используют информацию в том, что можно было бы считать постоянным потоком работ.5

Вы депонируете в своем банке чек своего шурина на $100, и, поскольку вы являетесь хорошим клиентом, деньги нисколько не задерживаются. Остаток на вашем счете увеличивается с $1000 до $1100. Информация о вашем банковском счете ассоциируется с чеком. Чек отсылается в банк вашего шурина. Позже, если чек возвращается в связи с отсутствием средств на счете шурина, с вашего счета снимется $130 (исходные $100 плюс $30 за отказ оплаты чека). Интересно, что решение об оптимистическом развитии событий основано на хорошем отношении банка лично к ВАМ. Для менее надежного клиента (такого, например, как ваш шурин) зачисление денег на счет было бы задержано (резервирование на случай потенциального отказа оплаты счета).6

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

Рассмотрим также учетную книгу, связанную с банковским счетом. В конце каждого месяца выпускается выписка по счету. Не требуется, чтобы она была абсолютно точной. Какой-либо чек, выпущенный в полночь 31-го числа данного месяца, может попасть в выписку как этого, так и следующего месяца. Учитываются поступления на счет и снятия со счета. Выпущенная выписка является постоянной и неизменной. Ошибки в мартовской выписке могут быть исправлены в апрельской выписке, но мартовская выписка никогда не изменится.

Рис. 7. В упрощенной схеме обработки имеются два основных аспекта: (1) запоминание всего, что встречается, и (2) принятие решение о том, не следует ли отклонить оплату чека.

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

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

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

ОЧЕНЬ вероятно, что банковская система, основанная на ненадежных компьютерах без фальшполов, операторов и систем резервного питания, оказалась бы более экономически эффективной, чем дорогостоящая централизованная система. Как показано выше, разделение работы на запоминания, предположения и извинения – это ровно то, как сегодня работают банки.

6.3 Согласованность "рано или поздно" и приложения

В обоих приведенных выше примерах уникально идентифицируемая работа поступает в систему и обрабатывается одной из ее реплик. Эта работа распространяется в другие реплики, когда с ними имеется связь.

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

6.4 Согласованность "рано или поздно" и хранение данных

Интересно, что значительная часть публикаций, посвященных согласованности "рано или поздно", фокусируется на семантике операций чтения и записи. Например, в недавней статье Вернера Фогельса (Werner Vogels) [20] разъясняются многие понятия из области согласованности "рано или поздно", но обсуждение ведется в контексте клиентов, систем хранения данных и операций модификации.

В статье про Amazon Dynamo [18] затрагивается много интересных тем и показывается, каким образом в Dynamo сохраняются BLOB'ы с доступом к значениям по ключу. Кроме того, в подразделе 4.4 про версии данных обсуждается использование операций "добавить покупку в корзину" и "удалить покупку из корзины" и то, как эти операции фиксируются в BLOB'ах, хранение которых поддерживает Dynamo. Даже если истории версий переупорядочиваются, покупки, добавленные в корзину, не будут потеряны, если только соответствующая версия BLOB'a не откажет вместе с другими версиями. Случайно удаленные покупки появятся снова.

Системы хранения сами по себе не могут обеспечить коммутативность, требуемую для создания устойчивых систем, функционирующих с применением асинхронных контрольных точек. Для обеспечения возможности переупорядочивания нужны бизнес-операции. Система Dynamo не делает этого сама по себе. За семантику согласованности "рано или поздно" и коммутативность отвечает приложение Shopping Cart, работающее поверх системы хранения Dynamo.

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

6.5 "Операционно-центрический" подход"
Оба примера, приведенные в начале раздела, демонстрируют улавливание потребностей приложения.

В примере с корзиной покупок операции "добавить покупку в корзину" и "удалить покупку из корзины" используются для фиксации намерений пользователей, когда они добавляют покупки в корзину и удаляют их из корзины. В хранилище BLOB'ов Dynamo использование этого операционно-центрического подхода обеспечивает устойчивость к случайному чередованию версий, происходящему из-за репликации и предпочтения доступности перед согласованностью. Интересно отметить, что операционно-центрическую работу можно сделать коммутативной (при выборе правильных операций и правильной семантики), в то время как использование семантики операций чтения и записи само по себе не приводит к коммутативности.

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

7. Управление ресурсами с применением асинхронности

В этом разделе обсуждаются особенности управления ресурсами при асинхронной установке контрольных точек, а также возможность независимой и потенциально избыточной работы. Сначала мы обсудим распределение ресурсов в слабо связанных системах, и следует ли обеспечивать их избыточное (over-booked) или же гарантированное (over-provisioned) резевирование. После этого мы отметим, что при наличии аварийных ситуаций или других ошибок компьютерные оценки не обязательно отражают состояние реального мира. Далее мы рассмотрим пример консервативного (гарантированного) подхода к распределению ресурсов в системах бронирования мест (seat-reservation). Затем мы проанализируем преимущества однородности (взаимозаменяемости) ресурсов в тех ситуациях, когда это возможно. После этого мы обсудим использование уникальных идентификаторов при обработке асинхронных запросов. Вслед за этим мы проанализируем связь согласованности "рано или поздно" и асинхронного управления ресурсами. В заключение раздела мы рассмотрим паттерны, использовавшиеся в бизнесе до появления компьютеров, и их использование при разработке слабо связанных систем.
7.1 Избыточное и гарантированное резервирование

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

  1. Гарантированное выделение (Over-Provisioning). При этом подходе у каждой реплики имеется фиксированное подмножество ресурсов, которые она может распределять. Если на складе имеется 1000 книг, то у каждой реплики может иметься по 500 книг для продажи. При гарантированном выделении реплика не может сделать ошибку при выделении ресурса, который в действительности выделен быть не может. С другой стороны, гарантированность выделения означает, что внутри реплик будут удерживаться избыточные ресурсы.
  2. Избыточное резервирование (Over-Booking). В отличие от гарантированного выделения, при избыточном резервировании допускается возможность того, что разъединенные реплики время от времени будут обещать нечто такое, что они не смогут обеспечить. Из-за того, что допускается независимое резервирование ресурсов без обеспечения их строгого разделения, иногда реплики берут на себя некоторые обязательства, которые не могут выполнить. С другой стороны, иногда удастся обрабатывать запросы, которые были бы отклонены при гарантированном выделении на основе строгого разделения ресурсов.

Можно придерживаться консервативной политики и гарантировать, что НИКОГДА не придется оправдываться перед клиентами. Однако иногда это будет приводить к отказу от выполнения работы, которую можно было бы выполнить. Можно принять к выполнению работу в отсоединенной реплике без уверенности в возможности соблюдения своих обязательств. Можно динамически перемещаться между двумя этими позициями (когда между репликами имеется связь) и регулировать вероятности и возможности.

При отсутствии связи вы не знаете точного ответа и должны применять бизнес-политику, допускающую компромиссы, приемлемые для вашего бизнеса!

7.2 Компьютинг и реальная действительность

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

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

Даже если компьютерные системы были бы совершенны, бизнес невозможен без извинений, поскольку непредвиденные ситуации неизбежны!

7.3 Пример с бронированием мест

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

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

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

  1. {"доступное"}
  2. {"ожидающее покупки билета", идентификатор сессии}
  3. {"купленное", идентификатор покупателя}
Для перевода мест из одного состояния в другое (в том числе, для возвращения в состояние "доступное" места, слишком долго ожидавшего покупки) используются отдельные транзакции базы данных.

В этом примере подход к распределению ресурсов ближе к "гарантированному выделению". Места считаются уникальными, и требуется координация основной и резервной системы для обеспечения консервативного (т.е. гарантированного) управления ресурсами. Чтобы избежать этой проблемы, нужно создавать пулы ресурсов.

7.4 Поиск взаимозаменяемости

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

Взглянем теперь на свиную грудинку. При чем здесь свиная грудинка? Дело в том, что этот термин описывает целую кучу свинины7. Существование грудинки как единицы фьючерсных контрактов служит мощным финансовым механизмом, поддерживающим свиноводство. Фермеры могут продовать своих свиней до того, как они достигнут кондиции, и тем самым ослаблять свои риски.

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

7.5 Важность уникальных идентификаторов

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

Таким образом, при рассмотрении темы управления ресурсами при наличии асинхронности мы видим важность наличия уникально идентифицируемых ресурсов, что позволяет нам добиться идемпотентного поведения.

7.6 В конце концов мы поговорим и станем согласованными

Когда отсоединенные реплики работают независимо, они накапливают операции. Это схоже с тем, как реплика обработчика банковского счета производит клиринг одних чеков, но не других. Это также схоже с тем, как в BLOB'е, управляемом Dynamo, сохраняются результаты некоторых операций над корзиной покупок (например, "Добавить в корзину" и "Удалить из корзины"), а результаты других операций отсутствуют из-за временных соотношений управления версиями.

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

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

7.7 Назад в будущее

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

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


4Мы рекомендуем классическую книгу "Zen and the Art of Motorcycle Maintenance" [2]. Точка зрения лузера в духе дзэн-будизма помогает в компьютинге и в личной жизни...

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

6Имеет смысл основывать решение на отношении лично к ВАМ... Это единственная информация, доступная банку в локальном режиме, и расходы будут оплачены ВАМИ с большей вероятностью, чем банком.

7В Википедии свиная грудинка описывается как нижняя часть туши свиньи, из которой делают бекон. Единицей контракта служат 20 тонн замороженной грудинки. См. [21].

Назад Содержание Вперёд

Новости мира IT:

Архив новостей

Последние комментарии:

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 985 1945361
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2015 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...