# Apache Spark: Как устроены распределенные вычисления и почему память важнее диска

Источник: https://www.youtube.com/watch?v=jaMWmLq422U
Канал: Stanford Online
Опубликовано: 20.09.2024

---

## Распределенные вычисления и Apache Spark: Масштабируемость и отказоустойчивость
[[JUMP:00:04]]

Современные системы обработки данных, такие как инфраструктуры Google, Facebook и Amazon, требуют работы с огромными массивами информации, измеряемыми сотнями терабайт. Решением этой задачи стали так называемые «складские» компьютеры (warehouse-scale computers) — кластеры из тысяч стандартных серверов, объединенных в единую вычислительную среду. В данной статье рассматриваются подходы к программированию таких систем, роль Apache Spark и механизмы, обеспечивающие их эффективность и отказоустойчивость.

### Архитектура «складских» компьютеров и проблема ввода-вывода
[[JUMP:05:01]]

Концепция «складского» компьютера, популяризированная Луисом Баррозу (Luiz Barroso) в его книге *Datacenter as a Computer*, предполагает использование товарных ПК (commodity PCs), соединенных через Ethernet. Основная мотивация перехода от одиночных узлов к кластерам — необходимость повышения пропускной способности ввода-вывода (I/O bandwidth). Обработка данных, которая на одном узле заняла бы 23 дня, на 1000 узлах выполняется за 33 минуты.

Основные особенности архитектуры:

*   **Иерархия сети:** Узлы объединены в стойки, на вершине каждой из которых находится коммутатор (top-of-rack switch). Скорость сети внутри стойки значительно выше, чем между стойками.
*   **Иерархия памяти:** Существует колоссальный разрыв в пропускной способности между оперативной памятью (DRAM) и сетью/дисками (дискретные величины до двух порядков).
*   **Отказоустойчивость:** При масштабах в тысячи серверов поломки происходят ежечасно, даже если среднее время безотказной работы одного узла составляет 25 лет.

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

### Распределенные файловые системы: Хранение данных
[[JUMP:18:02]]

Для предотвращения потери данных в случае выхода из строя узла или коммутатора стойки, используется распределенная файловая система (например, Google File System — GFS, или ее open-source аналог HDFS).

*   **Разделение:** Файлы разбиваются на блоки (обычно 64–256 МБ).
*   **Репликация:** Блоки копируются на разные узлы, предпочтительно в разных стойках.
*   **Управление:** Мастер-узел (name node) хранит метаданные о расположении реплик. Клиенты обращаются к нему, чтобы узнать, где находятся блоки, а затем читают данные напрямую с узлов-хранилищ (data nodes).

### Модель MapReduce: Первые шаги к автоматизации
[[JUMP:27:39]]

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

1.  **Map:** Применяет функцию к каждому элементу входных данных, не мутируя их, что обеспечивает легкую параллелизуемость и возможность повторного выполнения.
2.  **Shuffle/Sort:** Промежуточный этап, гарантирующий, что все значения с одинаковыми ключами попадут к одному редусеру.
3.  **Reduce:** Агрегирует значения для каждого ключа.

Эта модель эффективно справляется с отказами: если узел с mapper-задачей умирает, scheduler перезапускает задачу на другом узле, используя реплицированные данные. Однако MapReduce имеет существенные ограничения: модель линейна и неэффективна для итеративных алгоритмов (например, PageRank), так как требует записи каждого промежуточного результата на диск.

### Apache Spark и Resilient Distributed Datasets (RDD)
[[JUMP:58:36]]

Apache Spark был разработан для преодоления недостатков MapReduce, прежде всего за счет интенсивного использования оперативной памяти. Ключевой абстракцией здесь является **Resilient Distributed Dataset (RDD)** — неизменяемая, распределенная коллекция записей.

*   **Lineage (Родословная):** Spark отслеживает цепочку преобразований, создавших RDD. Это позволяет восстановить данные в случае сбоя без необходимости постоянной записи на диск.
*   **Преобразования и действия:** Spark разделяет операции на трансформации (создают новые RDD: `map`, `filter`, `join`) и действия (возвращают результат: `collect`, `count`).
*   **Оптимизация:** Spark автоматически анализирует зависимости между RDD. «Узкие» зависимости (narrow dependencies) позволяют выполнять оптимизации, такие как слияние циклов (fusion), что значительно повышает производительность за счет снижения нагрузки на память.