книга высоконагруженные приложения программирование масштабирование поддержка
Книга «Высоконагруженные приложения. Программирование, масштабирование, поддержка»
В этой книге вы найдете ключевые принципы, алгоритмы и компромиссы, без которых не обойтись при разработке высоконагруженных систем для работы с данными. Материал рассматривается на примере внутреннего устройства популярных программных пакетов и фреймворков. В книге три основные части, посвященные, прежде всего, теоретическим аспектам работы с распределенными системами и базами данных. От читателя требуются базовые знания SQL и принципов работы баз данных.
В обзорном посте рассматривается раздел «Знание, истина и ложь».
Если у вас нет опыта работы с распределенными системами, то последствия этих проблем могут оказаться весьма дезориентирующими. Узел сети ничего не знает наверняка — он способен только делать предположения на основе получаемых (или не получаемых) им по сети сообщений. Один узел в силе узнать состояние другого узла (какие данные на нем хранятся, правильно ли он работает), только обмениваясь с ним сообщениями. Если удаленный узел не отвечает, то нет никакого способа выяснить его состояние, поскольку невозможно отличить сетевые проблемы от проблем в узле.
Обсуждения этих систем граничат с философией: что в нашей системе правда, а что ложь? Можем ли мы полагаться на это знание, если механизмы познания и измерения ненадежны? Должны ли программные системы подчиняться законам физического мира, например закону причины и следствия?
К счастью, нам не требуется искать смысл жизни. Для распределенной системы можно описать допущения относительно поведения (модель системы) и спроектировать ее так, чтобы она соответствовала этим допущениям. Существует возможность проверки корректной работы алгоритмов в рамках определенной модели системы. А значит, надежность вполне достижима, даже если лежащая в основе системы модель обеспечивает очень мало гарантий.
Однако хотя можно обеспечить должную работу системы при ненадежной модели, сделать это непросто. В оставшейся части главы мы обсудим понятия знания и истины в распределенных системах, что поможет нам разобраться с нужными допущениями и гарантиями. В главе 9 мы перейдем к рассмотрению ряда примеров распределенных систем и алгоритмов, которые обеспечивают конкретные гарантии при конкретных допущениях.
Истина определяется большинством
Представьте сеть с асимметричным сбоем: узел получает все отправляемые ему сообщения, но все его исходящие сообщения задерживаются или вообще отбрасываются. И хотя он отлично работает и получает запросы от других узлов, эти другие не получают его ответов. Как следствие, по истечении некоторого времени ожидания другие узлы объявляют его неработающим. Ситуация превращается в какой-то кошмар: наполовину отключенный от сети узел насильно тащат «накладбище», а он отбивается и кричит: «Я жив!». Но, поскольку никто его криков не слышит, похоронная процессия неуклонно продолжает движение.
В чуть-чуть менее кошмарном сценарии наполовину отключенный от сети узел может заметить отсутствие подтверждений доставки своих сообщений от других узлов и понимает, что имеет место сбой сети. Тем не менее другие узлы ошибочно объявляют наполовину отключенный узел неработающим, а он не способен ничего с этим поделать.
В качестве третьего сценария представьте узел, приостановленный на долгое время в связи с длительной всеобъемлющей сборкой мусора. Все его потоки вытесняются из памяти процессом сборки мусора и приостанавливаются на минуту, и, следовательно, запросы не обрабатываются, а ответы не отправляются. Другие узлы ждут, повторяют отправку, теряют терпение, в конце концов объявляют узел неработающим и «отправляют его в катафалк». Наконец процесс сборки мусора завершает работу и потоки узла возобновляют работу как ни в чем не бывало. Остальные узлы удивляются «воскрешению» в полном здравии объявленного «мертвым» узла и начинают радостно болтать с очевидцами этого. Сначала данный узел даже не понимает, что прошла целая минута и он был объявлен «мертвым», — с его точки зрения с момента последнего обмена сообщениями с другими узлами прошло едва ли не мгновение.
Мораль этих историй: узел не может полагаться только на свое собственное мнение о ситуации. Распределенная система не может всецело полагаться на один узел, поскольку он способен отказать в любой момент, приведя к отказу и невозможности восстановления системы. Вместо этого многие распределенные алгоритмы основывают свою работу на кворуме, то есть решении большинства узлов (см. пункт «Операции записи и чтения по кворуму» подраздела «Запись в базу данных при отказе одного из узлов» раздела 5.4): принятие решений требует определенного минимального количества «голосов» от нескольких узлов. Данное условие позволяет снизить зависимость от любого одного конкретного узла.
Это включает принятие решений об объявлении узлов неработающими. Если кворум узлов объявляет другой узел неработающим, то он считается таковым, пусть и прекрасно работает в то же время. Отдельные узлы обязаны подчиняться решениям кворума.
Обычно кворум представляет собой абсолютное большинство от более чем половины узлов (хотя существуют и другие разновидности кворумов). Кворум по большинству позволяет системе работать в случае сбоев отдельных узлов (при трех узлах допустим отказ одного, при пяти — отказ двух). Такой способ безопасен, поскольку система может насчитывать только одно большинство — два большинства одновременно, чьи решения конфликтуют, невозможны. Мы обсудим использование кворумов подробнее, когда доберемся до алгоритмов консенсуса в главе 9.
Ведущий узел и блокировки
Зачастую системе необходимо наличие только одного экземпляра чего-либо. Например:
Случай, когда узел продолжает вести себя как «избранный», несмотря на то, что кворум остальных узлов объявил его неработающим, может привести к проблемам в недостаточно тщательно спроектированной системе. Подобный узел способен отправлять сообщения другим узлам в качестве самозваного «избранного», и если другие узлы с этим согласятся, то система в целом может начать работать неправильно.
Например, на рис. 8.4 показана ошибка с порчей данных вследствие неправильной реализации блокировки (это отнюдь не теоретическая ошибка: она часто возникает в СУБД HBase). Допустим, мы хотели бы убедиться, что одновременно обратиться к находящемуся в сервисе хранения файлу может только один клиент, поскольку, если несколько клиентов сразу попытаются выполнить в него запись, файл будет испорчен. Мы попытаемся реализовать это с помощью обязательного получения клиентом договора аренды от сервиса блокировок до обращения к файлу.
Описанная проблема представляет собой пример того, что мы обсуждали в подразделе «Паузы при выполнении процессов» раздела 8.3: если арендующий клиент приостанавливается слишком надолго, то срок его договора аренды истекает. После этого другой клиент может получить договор аренды на тот же файл и начать запись в него данных. После возобновления работы приостановленный клиент верит (ошибочно), что у него все еще есть действующий договор аренды, и переходит к записи в файл. В результате операции записи двух клиентов перемешиваются и файл портится.
Ограждающие маркеры
При использовании блокировки или договора аренды для защиты доступа к какому-либо ресурсу, например файловому хранилищу на рис. 8.4, необходимо убедиться, что узел, ошибочно считающий себя «избранным», не нарушит работу всей остальной системы. Для этой цели существует достаточно простой метод, показанный на рис. 8.5. Он называется ограждением (fencing).
Представим, что при каждом предоставлении блокировки или договора аренды сервер блокировок также возвращает ограждающий маркер (fencing token), представляющий собой номер, наращиваемый при каждом предоставлении блокировки (например, его может наращивать сервис блокировок). Кроме того, потребуем, чтобы клиент при каждой отправке запроса на запись сервису хранения включал в текущий запрос такой маркер.
На рис. 8.5 клиент 1 получает договор аренды с маркером 33, после чего надолго приостанавливается, и срок договора аренды истекает. Клиент 2 получает договор аренды с маркером 34 (номер монотонно возрастает), после чего отправляет запрос на запись сервису хранения, включая в запрос этот маркер. Позднее клиент 1 возобновляет работу и отправляет сервису хранения операцию записи с маркером 33. Однако сервис хранения помнит, что уже обработал операцию записи с большим номером маркера (34) и отклоняет данный запрос.
При использовании в качестве сервиса блокировок ZooKeeper в роли ограждающего маркера можно задействовать идентификатор транзакции zxid или версию узла cversion. Поскольку ZooKeeper гарантирует их монотонное возрастание, они обладают нужными для этого свойствами.
Обратите внимание: этот механизм требует, чтобы сам ресурс принимал активное участие в проверке маркеров, отклоняя все операции записи с маркерами, более старыми, чем уже обработанные, — проверки статуса блокировки на самих клиентах недостаточно. Можно обойти ограничение и для ресурсов, не поддерживающих явным образом ограждающие маркеры (например, в случае сервиса хранения файлов ограждающий маркер включается в имя файла). Однако некоторая проверка все равно нужна, во избежание обработки запросов без защиты блокировкой.
Проверка маркеров на стороне сервера может показаться недостатком, но, вполне вероятно, это не так уж плохо: для сервиса было бы неразумно считать, что все его клиенты всегда «ведут себя хорошо», поскольку клиенты часто запускают люди совсем не с такими приоритетами, как у владельцев сервиса. Следовательно, для любого сервиса будет хорошей идеей защищаться от непредумышленных неправильных действий со стороны клиентов.
Византийские сбои
Ограждающие маркеры способны обнаруживать и блокировать узел, непреднамеренно выполняющий ошибочные действия (например, потому, что еще не обнаружил истечение срока его договора аренды). Однако узел, умышленно желающий подорвать системные гарантии, может легко это сделать, отправив сообщение с поддельным маркером.
В этой книге мы предполагаем, что узлы ненадежны, но «добропорядочны»: они могут работать медленно или не отвечать вообще (вследствие сбоя), их состояние может быть устаревшим (из-за паузы на сборку мусора или сетевых задержек), но если узел вообще отвечает, то он «говорит правду» (соблюдает правила протокола в рамках имеющейся у него информации).
Проблемы распределенных систем значительно усугубляются при наличии риска, что узлы могут «лгать» (отправлять произвольные сбойные или поврежденные ответы) — например, если узел может заявить о получении определенного сообщения, когда на самом деле этого не было. Подобное поведение носит название византийского сбоя (Byzantine fault), и задача достижения консенсуса в подобной, не заслуживающей доверия среде известна как задача византийских генералов (Byzantine generals problem).
Система защищена от византийских сбоев, если продолжает работать правильно даже в случае нарушения работоспособности некоторых узлов и не соблюдения ими протокола или при вмешательстве злоумышленников в работу сети. Это может быть важно в следующих обстоятельствах.
В то же время веб-приложениям имеет смысл ожидать произвольного и злонамеренного поведения от находящихся под контролем конечных пользователей клиентов, например браузеров. Поэтому проверка вводимых данных, контроль корректности и экранирование вывода столь важны: например, для предотвращения внедрения SQL-кода (SQL injection) и межсайтового выполнения сценариев (cross-site scripting). Однако при этом обычно не применяются защищенные от византийских сбоев протоколы, а серверу просто делегируются полномочия принятия решения, допустимо ли поведение клиента. В одноранговых сетях, где подобного центрального органа нет, защищенность от византийских сбоев более уместна.
Можно рассматривать ошибки в программном обеспечении как византийские сбои, однако если одно и то же ПО используется во всех узлах, то алгоритмы защиты от византийских сбоев вас не спасут. Большинство таких алгоритмов требуют квалифицированного большинства из более чем двух третей нормально работающих узлов (то есть в случае четырех узлов может не работать максимум один). Чтобы решить проблему ошибок с помощью такого подхода, вам пришлось бы использовать четыре независимые реализации одного и того же программного обеспечения и надеяться на присутствие ошибки только в одной из них.
Аналогично кажется заманчивым, чтобы сам протокол защищал нас от уязвимостей, нарушений требований безопасности и злонамеренных действий. К сожалению, в большинстве систем это нереально. Если злоумышленник сумеет получить несанкционированный доступ к одному узлу, то очень вероятно, что сможет получить доступ и к остальным, поскольку на них, скорее всего, работает одно и то же программное обеспечение. Следовательно, традиционные механизмы (аутентификация, контроль доступа, шифрование, брандмауэры и т. д.) остаются основной защитой от атак.
Слабые формы «лжи». Хотя мы предполагаем, что узлы преимущественно «добропорядочны», имеет смысл добавить в ПО механизмы защиты от слабых форм «лжи» — например, некорректных сообщений вследствие аппаратных проблем, ошибок в программном обеспечении и неправильных настроек. Подобные механизмы нельзя считать полномасштабной защитой от византийских сбоев, ведь они не смогут спасти от решительно настроенного злоумышленника, но это простые и практичные шаги по усилению надежности. Вот несколько примеров.
Модели системы на практике
Для решения задач распределенных систем было разработано множество алгоритмов, например, мы рассмотрим решения для задачи консенсуса в главе 9. Чтобы принести какую-то пользу, эти алгоритмы должны уметь справляться с различными сбоями распределенных систем, которые мы обсуждали в этой главе.
Алгоритмы должны как можно меньше зависеть от особенностей аппаратного обеспечения и настроек ПО системы, на которой они работают. Это, в свою очередь, требует формализации типов вероятных сбоев. Для этого мы опишем модель системы — абстракцию, описывающую принимаемые алгоритмом допущения.
Что касается допущений по хронометражу, часто используются три системные модели.
Корректность алгоритмов
Чтобы дать определение корректности (correctness) алгоритма, я опишу его свойства. Например, у результатов работы алгоритма сортировки есть следующее свойство: для любых двух различных элементов выходного списка элемент слева меньше, чем элемент справа. Это просто формальный способ описания сортировки списка.
Аналогично формулируются свойства, которые требуются от корректного распределенного алгоритма. Например, при генерации ограждающих маркеров для блокировки можно требовать от алгоритма следующие свойства:
Высоконагруженные приложения. Программирование, масштабирование, поддержка (pdf+epub)
Посоветуйте книгу друзьям! Друзьям – скидка 10%, вам – рубли
Эта и ещё 2 книги за 299 ₽
В этой книге вы найдете ключевые принципы, алгоритмы и компромиссы, без которых не обойтись при разработке высоконагруженных систем для работы с данными. Материал рассматривается на примере внутреннего устройства популярных программных пакетов и фреймворков. В книге три основные части, посвященные, прежде всего, теоретическим аспектам работы с распределенными системами и базами данных. От читателя требуются базовые знания SQL и принципов работы баз данных.
С этой книгой читают
Отзывы 5
Не могу что-либо про перевод сказать, читал данную книгу в оригинале. Очень толково и по делу описаны базы данных и интерфейсы. С другой же стороны – половину книги можно вырезать без какой либо потери в качестве и содержании…
Не могу что-либо про перевод сказать, читал данную книгу в оригинале. Очень толково и по делу описаны базы данных и интерфейсы. С другой же стороны – половину книги можно вырезать без какой либо потери в качестве и содержании…
Altmann Nicolas, hello world
Altmann Nicolas, hello world
Отличная книга, раскрывающая внутреннее устройство баз данных. Даёт понимание, в каких сценариях использовать БД того или иного класса.
Да, ее можно было бы сократить, убрав различные обороты, подводки и вопросы, на которые автор сам же и отвечает. Тем не менее, считаю, что это не критично и, более того, способствует усвоению материала
Отличная книга, раскрывающая внутреннее устройство баз данных. Даёт понимание, в каких сценариях использовать БД того или иного класса.
Да, ее можно было бы сократить, убрав различные обороты, подводки и вопросы, на которые автор сам же и отвечает. Тем не менее, считаю, что это не критично и, более того, способствует усвоению материала
Книга хорошая, но будьте внимательны, доступен только PDF формат, который проблематично читать на мобильном устройстве.
Бумажную версию тоже не советую – качество печати отвратительное, годится только чтобы на полочку поставить. Шрифт иногда плывет, страницы очень тонкие и просвечиваются.
Перевод может и хороший, но факты выше все портят. Читайте оригинал.
Книга хорошая, но будьте внимательны, доступен только PDF формат, который проблематично читать на мобильном устройстве.
Бумажную версию тоже не советую – качество печати отвратительное, годится только чтобы на полочку поставить. Шрифт иногда плывет, страницы очень тонкие и просвечиваются.
Перевод может и хороший, но факты выше все портят. Читайте оригинал.
не Отличная книга! Прекрасная глава про распределенные вычисления. Прекрасная глава про распределенные вычисления. Прекрасная глава про распределенные вычисления.
не Отличная книга! Прекрасная глава про распределенные вычисления. Прекрасная глава про распределенные вычисления. Прекрасная глава про распределенные вычисления.
Книга претендует на звание «must read» для разработчика отказоустойчивых систем. Представляет собой в первую очередь и в большей мере учебник, нежели справочник. Книга в полной мере раскрывает принципы функционирования самых разных баз данных. Но это далеко не всё, в книге описаны подходы и общие принципы к решению проблем отказов узлов в распределенных системах, выходящие за границы области баз данных. В русскоязычных сообществах книга зовется «кабанчик» и стала классикой в области разработки и проектирования распределенных отказоустойчивых решений. Отмечу высокий порог вхождения для некоторых деталей книги, в том числе B-деревья, алгоритмы консенсуса, и другие математические моменты.
Книга претендует на звание «must read» для разработчика отказоустойчивых систем. Представляет собой в первую очередь и в большей мере учебник, нежели справочник. Книга в полной мере раскрывает принципы функционирования самых разных баз данных. Но это далеко не всё, в книге описаны подходы и общие принципы к решению проблем отказов узлов в распределенных системах, выходящие за границы области баз данных. В русскоязычных сообществах книга зовется «кабанчик» и стала классикой в области разработки и проектирования распределенных отказоустойчивых решений. Отмечу высокий порог вхождения для некоторых деталей книги, в том числе B-деревья, алгоритмы консенсуса, и другие математические моменты.
Книга высоконагруженные приложения программирование масштабирование поддержка
Высоконагруженные приложения. Программирование, масштабирование, поддержка.
В книге Мартина Клеппмана «Высоконагруженные приложения: Программирование, масштабирование, поддержка» вы найдете ключевые принципы, алгоритмы и компромиссы, без которых не обойтись при разработке высоконагруженных систем для работы с данными. Цель издания — помочь вам проложить маршрут по многоликому и быстро меняющемуся ландшафту технологий для обработки и хранения данных. Эта книга — не учебное пособие по одному конкретному инструменту и не учебник, набитый сухой теорией. Напротив, вы изучите примеры успешно работающих информационных систем: технологий, которые составляют фундамент множества популярных приложений и в промышленной эксплуатации ежедневно должны отвечать требованиям по масштабированию, производительности и надежности. Вы узнаете внутреннее устройство этих систем, разберетесь в ключевых алгоритмах, обсудите их принципы и неизбежные компромиссы. В процессе попытаемся отыскать удобные подходы к информационным системам — не только к тому, как они работают, но и почему они работают именно так, а также какие вопросы необходимо задать себе о них.
После прочтения этой книги вы сможете решить, для каких задач подходят различные технологии, и понять принципы сочетания инструментов с целью закладки фундамента архитектуры хорошего приложения. Вряд ли вы будете готовы к созданию с нуля своей собственной подсистемы хранения базы данных, но это, к счастью, требуется редко. Однако вы сумеете развить интуицию в отношении происходящего «за кулисами» ваших систем, что позволит судить об их поведении, принимать хорошие проектные решения и обнаруживать любые возникающие проблемы. Если вы разрабатываете приложения, включающие какую-либо серверную/прикладную часть для хранения или обработки данных и использующие Интернет (например, веб-приложения, мобильные приложения либо подключенные через Сеть датчики), то эта книга — для вас.
Издание предназначено для разработчиков программного обеспечения, архитекторов ПО и технических директоров, которые в свободное время любят писать код. Оно особенно актуально, если вам нужно принять решение об архитектуре систем, над которыми вы работаете, — например, выбрать инструменты для решения конкретной проблемы и придумать, как их лучше использовать. Но даже если у вас нет права выбирать инструменты, данная книга поможет понять их достоинства и недостатки.
Высоконагруженные приложения
Программирование, масштабирование, поддержка.
Клеппман М. «Высоконагруженные приложения» Питер, 2018 год, 640 с., O’Reilly, ISBN 978-5-4461-0512-0; (PDF)
В этой книге вы найдете ключевые принципы, алгоритмы и компромиссы, без которых не обойтись при разработке высоконагруженных систем для работы с данными. Материал рассматривается на примере внутреннего устройства популярных программных пакетов и фреймворков. В книге три основные части, посвященные, прежде всего, теоретическим аспектам работы с распределенными системами и базами данных. От читателя требуются базовые знания SQL и принципов работы баз данных.
Цель издания — помочь читателю изучить технологии для обработки и хранения данных. В книге представлены примеры успешно работающих информационных систем: технологий, которые составляют фундамент множества популярных приложений, которые ежедневно работают и при этом должны отвечать требованиям по масштабированию, производительности и надежности. Для разработчиков ПО.
ISBN 978-1449373320 англ.
ISBN 978-5-4461-0512-0
Содержание.
Часть I. Основы информационных систем
Глава 1. Надежные, масштабируемые и удобные в сопровождении приложения 23
1.1. Подходы к работе над информационными системами 24
1.2. Надежность 27
Аппаратные сбои 28
Программные ошибки 29
Человеческий фактор 30
Насколько важна надежность 31
1.3. Масштабируемость 32
Описание нагрузки 32
Описание производительности 36
Как справиться с нагрузкой 42
1.4. Удобство сопровождения 43
Удобство эксплуатации 44
Простота: регулируем сложность 45
Возможность развития: облегчаем внесение изменений 47
1.5. Резюме 47
1.6. Библиография 48
Глава 2. Модели данных и языки запросов 53
2.1. Реляционная модель в сравнении с документоориентированной
моделью 54
Рождение NoSQL 55
Объектно-реляционное несоответствие 56
Связи «многие-к-одному» и «многие-ко-многим» 59
Повторяется ли история в случае документоориентированных баз данных 62
Реляционные и документоориентированные базы данных сегодня 65
2.2. Языки запросов для данных 70
Декларативные запросы в Интернете 71
Выполнение запросов с помощью MapReduce 73
2.3. Графоподобные модели данных 76
Графы свойств 78
Язык запросов Cypher 79
Графовые запросы в SQL 81
Хранилища тройных кортежей и SPARQL 83
Фундамент: Datalog 88
2.4. Резюме 90
2.5. Библиография 92
Глава 3. Подсистемы хранения и извлечение данных 97
3.1. Базовые структуры данных БД 98
Хеш-индексы 100
SS-таблицы и LSM-деревья 104
B-деревья 108
Сравнение B- и LSM-деревьев 113
Другие индексные структуры 115
3.2. Обработка транзакций или аналитика? 120
Складирование данных 122
«Звезды» и «снежинки»: схемы для аналитики 125
3.3. Столбцовое хранилище 127
Сжатие столбцов 129
Порядок сортировки в столбцовом хранилище 131
Запись в столбцовое хранилище 132
Агрегирование: кубы данных и материализованные представления 133
3.4. Резюме 135
3.5. Библиография 136
Глава 4. Кодирование и эволюция 143
4.1. Форматы кодирования данных 144
Форматы, ориентированные на конкретные языки 145
JSON, XML и двоичные типы данных 146
Thrift и Protocol Buffers 150
Avro 154
Достоинства схем 160
4.2. Режимы движения данных 161
Поток данных через БД 162
Поток данных через сервисы: REST и RPC 164
Поток данных передачи сообщений 170
4.3. Резюме 173
4.4. Библиография 175
Часть II. Распределенные данные
Глава 5. Репликация 185
5.1. Ведущие и ведомые узлы 186
Синхронная и асинхронная репликация 188
Создание новых ведомых узлов 190
Перебои в обслуживании узлов 190
Реализация журналов репликации 193
5.2. Проблемы задержки репликации 196
Читаем свои же записи 197
Монотонные чтения 200
Согласованное префиксное чтение 201
Решения проблемы задержки репликации 202
5.3. Репликация с несколькими ведущими узлами 203
Сценарии использования репликации с несколькими
ведущими узлами 204
Обработка конфликтов записи 207
Топологии репликации с несколькими ведущими узлами 212
5.4. Репликация без ведущего узла 214
Запись в базу данных при отказе одного из узлов 215
Ограничения согласованности по кворуму 218
Нестрогие кворумы и направленная передача 221
Обнаружение конкурентных операций записи 222
5.5. Резюме 230
5.6. Библиография 232
Оглавление 9
Глава 6. Секционирование 239
6.1. Секционирование и репликация 240
6.2. Секционирование данных типа «ключ — значение» 241
Секционирование по диапазонам значений ключа 242
Секционирование по хешу ключа 243
Асимметричные нагрузки и разгрузка горячих точек 245
6.3. Секционирование и вторичные индексы 246
Секционирование вторичных индексов по документам 247
Секционирование вторичных индексов по термам 248
6.4. Перебалансировка секций 250
Методики перебалансировки 250
Эксплуатация: автоматическая или ручная перебалансировка 254
6.5. Маршрутизация запросов 255
6.6. Резюме 259
6.7. Библиография 260
Глава 7. Транзакции 265
7.1. Неустоявшаяся концепция транзакции 267
Смысл аббревиатуры ACID 267
Однообъектные и многообъектные операции 272
7.2. Слабые уровни изоляции 277
Чтение зафиксированных данных 279
Изоляция снимков состояния и воспроизводимое чтение 282
Предотвращение потери обновлений 288
Асимметрия записи и фантомы 292
7.3. Сериализуемость 298
Последовательное выполнение 299
Двухфазная блокировка (2PL) 304
Сериализуемая изоляция снимков состояния (SSI) 308
7.4. Резюме 314
7.5. Библиография 316
Глава 8. Проблемы распределенных систем 323
8.1. Сбои и частичные отказы 324
8.2. Ненадежные сети 328
Сетевые сбои на практике 329
Обнаружение сбоев 331
Время ожидания и неограниченные задержки 332
Асинхронные и синхронные сети 335
10 Оглавление
8.3. Ненадежные часы 338
Монотонные часы и часы истинного времени 339
Синхронизация часов и их точность 341
Ненадежность синхронизированных часов 343
Паузы при выполнении процессов 348
8.4. Знание, истина и ложь 353
Истина определяется большинством 353
Византийские сбои 357
Модели системы на практике 360
8.5. Резюме 364
8.6. Библиография 366
Глава 9. Согласованность и консенсус 375
9.1. Гарантии согласованности 376
9.2. Линеаризуемость 378
Что делает систему линеаризуемой 379
Опора на линеаризуемость 384
Реализация линеаризуемых систем 387
Цена линеаризуемости 390
9.3. Гарантии упорядоченности 394
Порядок и причинность 395
Упорядоченность по порядковым номерам 399
Рассылка общей последовательности 404
9.4. Распределенные транзакции и консенсус 409
Атомарная и двухфазная фиксация 411
Распределенные транзакции на практике 417
Отказоустойчивый консенсус 422
Сервисы членства и координации 428
9.5. Резюме 432
9.6. Библиография 435
Часть III. Производные данные
III.1. Системы записи и производные данные 446
III.2. Обзор глав 447
Глава 10. Пакетная обработка 449
10.1. Пакетная обработка средствами Unix 451
Простой анализ журнала 452
Философия Unix 454
10.2. MapReduce и распределенные файловые системы 458
Выполнение задач в MapReduce 460
Объединение и группировка на этапе сжатия 464
Объединения на этапе сопоставления 470
Выходные данные пакетных потоков 473
Сравнение Hadoop и распределенных баз данных 478
10.3. За пределами MapReduce 482
Материализация промежуточного состояния 483
Графы и итеративная обработка 488
API и языки высокого уровня 491
10.4. Резюме 494
10.5. Библиография 496
Глава 11. Потоковая обработка 505
11.1. Передача потоков событий 506
Системы обмена сообщениями 507
Секционирование журналов 513
11.2. Базы данных и потоки 519
Синхронизация систем 519
Перехват изменений данных 521
Источники событий 525
Состояние, потоки и неизменяемость 528
11.3. Обработка потоков 533
Применение обработки потоков 534
Рассуждения о времени 538
Объединения потоков 543
Отказоустойчивость 547
11.4. Резюме 551
11.5. Библиография 553
Глава 12. Будущее информационных систем 563
12.1. Интеграция данных 564
Объединение специализированных инструментов путем сбора
информации 565
Пакетная и потоковая обработка 569
12.2. Отделение от баз данных 574
Объединение технологий хранения данных 575
Проектирование приложений на основе потока данных 580
Наблюдение за производными состояниями 586
12.3. Стремление к корректности 594
Сквозные аргументы в базе данных 595
Принудительные ограничения 600
Своевременность и целостность 604
Доверяй, но проверяй 609
12.4. Делать что должно 614
Предсказательная аналитика 615
Конфиденциальность и отслеживание 619
12.5. Резюме 627
12.6. Библиография 628