Высоконагруженные приложения (Клеппман)

Материал из Народного Брифли
Перейти к:навигация, поиск
Этот пересказ создан с помощью искусственного интеллекта. Он может содержать ошибки. Вы можете помочь проекту, сверив его с оригинальным текстом, исправив ошибки и убрав этот шаблон.
В этом пересказе не указан источник, взятый за основу пересказа. См. руководство по поиску и указанию источника.
💾
Высоконагруженные приложения
Программирование, масштабирование, поддержка
англ. Designing Data-Intensive Applications. The Big Ideas Behind Reliable, Scalable, and Maintainable Systems · 2017
Краткое содержание книги
Оригинал читается за 1609 минут
Микропересказ
С ростом объёма данных одна машина перестаёт справляться. Чтобы система осталась надёжной, данные распределяют по кластеру, используя репликацию, транзакции и обработку потоков для масштабируемости.

Очень краткое содержание[ред.]

Книга посвящена проектированию высоконагруженных приложений, где основной проблемой становится объём, сложность и скорость изменения данных, а не производительность процессора. В первой части закладываются фундаментальные понятия: надёжность, масштабируемость и удобство сопровождения. Рассматриваются модели данных — от реляционной SQL-модели, созданной в 1970 году, до документоориентированных баз NoSQL. Описываются подсистемы хранения, индексы для ускорения поиска и форматы кодирования данных.

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

При построении надёжных систем важен принцип постепенного развития.

Любая работающая сложная система неизбежно выросла из работающей простой системы. Верно и обратное: сложная система, разработанная с нуля, никогда не будет работать, и её невозможно привести в рабочее состояние.

⚠️ Эта цитата слишком длинная: 211 зн. Максимальный размер: 200 знаков. См. руководство.

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

Подробный пересказ по главам[ред.]

Часть 1. Основы информационных систем[ред.]

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

👨🏻‍💻
Мартин Клеппман — автор книги, исследователь распределённых систем, специалист по высоконагруженным приложениям и архитектуре данных.

Глава 1. Надёжные, масштабируемые и удобные в сопровождении приложения[ред.]

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

Глава 2. Модели данных и языки запросов[ред.]

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

Модели данных — вероятно, важнейшая часть разработки программного обеспечения в силу оказываемого ими глубочайшего воздействия... на наше представление о решаемой проблеме.

Наиболее известной моделью данных признавалась SQL-модель, основанная на реляционной модели, созданной в 1970 году.

👨🏻‍🔬
Эдгар Кодд — исследователь IBM, создатель реляционной модели данных в 1970 году, основоположник SQL и современных баз данных.

Она организовывала данные в таблицы с неупорядоченными наборами строк. В 2010-х годах появилось движение NoSQL как попытка преодолеть ограничения реляционной модели. Причины его внедрения включали потребность в масштабировании для больших объёмов данных, предпочтение свободного программного обеспечения и разочарование в ограниченности реляционных схем. Документоориентированные базы данных возвращали к иерархической модели данных, хорошо работающей со связями «один-ко-многим», но испытывающей трудности со связями «многие-ко-многим».

Глава 3. Подсистемы хранения и извлечение данных[ред.]

Глава рассматривала основы подсистем хранения и извлечения данных в базах данных. Демонстрировалась простейшая база данных, реализованная в виде двух функций, использующая текстовый файл для хранения пар «ключ-значение». Подчёркивалась концепция добавления данных в конец файла, что являлось эффективной операцией записи. Однако производительность при чтении оказывалась крайне низкой, что приводило к необходимости использования индексов — дополнительных структур данных для ускорения поиска. Индексы ускоряли чтение, но замедляли запись.

Глава 4. Кодирование и эволюция[ред.]

Глава рассматривала вопросы эволюции приложений и данных, подчёркивая неизбежность изменений со временем. Акцентировалось внимание на концепции возможности развития, требующей адаптивных систем. Модификации приложений часто влекли за собой изменения в хранимых данных, что ставило задачи совместимости старых и новых форматов. Для обеспечения бесперебойной работы системы критически важной была совместимость в двух направлениях: обратная совместимость и прямая совместимость. Обсуждались различные форматы кодирования данных: JSON, XML, Protocol Buffers, Thrift и Avro, их реакции на изменения схемы и поддержка систем, где старые и новые данные сосуществовали.

Часть 2. Распределённые данные[ред.]

Вторая часть книги переходила от обсуждения систем данных на одной машине к вопросам, возникающим при участии нескольких машин в хранении и извлечении данных. Основной причиной для распределения баз данных по нескольким машинам называлась масштабируемость: если объём данных, нагрузка по чтению или записи превышали возможности одной машины, их можно было распределить на несколько компьютеров. Другими важными причинами являлись отказоустойчивость и высокая доступность, позволяющие приложению продолжать работу даже в случае сбоев.

Глава 5. Репликация[ред.]

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

Глава 6. Секционирование[ред.]

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

Глава 7. Транзакции[ред.]

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

Глава 8. Проблемы распределённых систем[ред.]

В отличие от программного обеспечения на одном компьютере, которое либо работало, либо нет, распределённые системы сталкивались с новыми и захватывающими проблемами. Выделялись три основных типа систем: сервисы, где важны время отклика и доступность; системы пакетной обработки, предназначенные для обработки больших объёмов данных в течение длительного времени; и системы поточной обработки, занимающие промежуточное положение.

Мораль этих историй: узел не может полагаться только на своё собственное мнение о ситуации. Распределённая система не может всецело полагаться на один узел, поскольку он способен отказать...

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

Глава 9. Согласованность и консенсус[ред.]

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

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

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

Часть 3. Производные данные[ред.]

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

Глава 10. Пакетная обработка[ред.]

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

Глава 11. Потоковая обработка[ред.]

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

Глава 12. Будущее информационных систем[ред.]

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

Интернет настолько хорош, что большинство людей считает его природным ресурсом... Когда в последний раз в технологии подобного масштаба не было ни одной ошибки?

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

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

⚠️ Эта цитата слишком длинная: 202 зн. Максимальный размер: 200 знаков. См. руководство.