Архитектура Facebook
Взято
отсюда
Мало ли кому пригодится, там спамить или траф привлекать
На сегодняшний день Facebook является пожалуй самым обсуждаемым интернет-проектом во всем мире. Не смотря на довольно низкий уровень проникновения Facebook в России, темпы захвата аудитории этим проектом мягко говоря поражают. Как же им удается управляться с таким огромным социальным графом и удовлетворять потребности в общении невероятно большого количества людей по всему миру?
Платформа
* Linux — операционная система
* PHP с HipHop — код на PHP компилируется в C++
* memcached — агрессивное кэширование объектов
* MySQL — используется как хранилище пар ключ-значение, никаких join'ов
* Thrift — интерфейс взаимодействия между сервисами, написанными на разных языках программирования
* Scribe — универсальная система сбора и агрегации данных с рабочих серверов
Статистика
* Более 500 миллионов активных пользователей (месячная аудитория)
* Более миллиарда социальных связей
* Более 200 миллиардов просмотров страниц в месяц
* Более 4 триллионов действий попадает в новостные ленты каждый день
* Более 150 миллионов обращений к кэшу в секунду; 2 триллиона объектов в кэше
* Более 8 миллиардов минут провели пользователи на Facebook'е ежедневно
* Более 3 миллиардов фотографий загружается каждый месяц, до 1.2 миллиона фотографий в секунду
* 20 миллиардов фотографий в 4 разрешениях = 80 миллиардов фотографий, их бы хватило чтобы покрыть поверхность земли в 10 слоев; это больше, чем на всех других фото-ресурсах в месте взятых
* О более чем 5 миллиардах единиц контента рассказывается друзьям еженедельно
* Более миллиарда сообщений в чате каждый день
* Более ста миллионов поисковых запросов в день
* Более 250 приложений и 80 тысяч сторонних ресурсов на платформе Facebook Connect
* Более 400 тысяч разработчиков сторонних приложений
* Менее 500 разработчиков и системных администраторов в штате
* Более миллиона активных пользователей на одного инженера
* Десятки тысяч серверов, десятки гигабит трафика
Архитектура
Общие принципы
* Балансировщик нагрузки выбирает веб-сервер для обработки запроса
* PHP-код в веб-сервере подготавливает HTML, пользуясь данными из различных источников:
o MySQL
o memcached
o Специализированные сервисы
* Если взглянуть с другой стороны, то получим трехуровневую архитектуру:
o Вер-приложение
o Распределенный индекс
o Постоянное хранилище
* Использование открытых технологий там, где это возможно
* Поиск возможностей оптимизации используемых продуктов
* Философия Unix:
o Старайтесь делать каждый компонент системы простым и производительным
o Комбинируйте компоненты для решения задач
o Концентрируйте внимание на хорошо обозначенных точках взаимодействия
* Все усилия направлены на масштабируемость
* Попытки минимизации количества точек отказа
* Простота, простота, простота!
PHP
Почему PHP?
* Во многом «так исторически сложилось»
* Хорошо подходит для веб-разработки
* Легок в изучении: небольшой набор выражений и языковых конструкций
* Легок в написании: нестрогая типизация и универсальный «массив»
* Легок в чтении: синтаксис похож на C++ и Java
* Прост в дебаггинге: нет необходимости в перекомпиляции
* Большой ассортимент библиотек, актуальных для веб-проектов
* Подходит для процесса разработки с короткими итерациями
* Активное сообщество разработчиков по всему миру
* Динамическая типизация, интерпретируемый язык для скриптов
Как оказалось на самом деле?
* Высокий расход оперативной памяти и вычислительных ресурсов
* Сложно работать, когда объем исходного кода очень велик: слабая типизация и ограниченные возможности для статичного анализа и оптимизации кода
* Не особо оптимизирован для использования в крупных проектах
* Линейный рост издержек при подключении файлов с исходным кодом
* Механизм разработки расширений не очень удобен
Доработки:
* Оптимизация байт-кода
* Улучшения в APC (ленивая загрузка, оптимизация блокировок, «подогрев» кэша)
* Свои расширения (клиент memcache, формат сериализации, логи, статистика, мониторинг, механизм асинхронной обработки событий)
* HipHop — трансформатор исходных кодов:
o Разработчики пишут на PHP, который конвертируется в оптимизированный C++
o Статический анализ, определение типов данных, генерация кода, и.т.д.
o Облегчает разработку расширений
o Существенно сокращает расходы оперативной памяти и вычислительных ресурсов
o У команды из трех программистов ушло полтора года на разработку, переписаны большая часть интерпретатора и многие расширения языка
o Опубликован под opensource лицензией в начале года, нет необходимости проходить этот же путь с нуля
MySQL
Как используется MySQL?
* Используется как хранилище пар ключ-значение
* Большое количество логических узлов распределено между физическими машинами
* Балансировка нагрузке на уровне физических серверов
* Репликация для распределения операций чтения не используется
* Большинство запросов касаются самой свежей информации: оптимизация таблиц для доступа к новым данным, архивация старых записей
* В целом быстро и надежно
Как оказалось на самом деле?
* Логическая миграция данных очень сложна
* Создавать большое количество логических баз данных и перераспределять их между физическими узлами, балансируя таким образом нагрузку, намного удобнее
* Никаких join'ов на рабочих серверах баз данных
* Намного проще наращивать вычислительные мощности на веб-серверах, чем на серверах баз данных
* Схемы, основанные на структуре данных, делают программистов счастливыми и создают большую головную боль администраторам
* Никогда не храните не-статичные данные в централизованное базе данных
Доработки:
* Практически никаких модификаций исходного кода MySQL
* Своя схема партиционирования с глобально-уникальными идентификаторами
* Своя схема архивирования, основанная на частоте доступа к данным относительно каждого пользователя
* Расширенный движок запросов для репликации между датацентрами и поддержания консистенции кеша
* Библиотеки для доступа к данным на основе графа:
o Объекты (вершины графа) с ограниченными типами данных (целое число, строка ограниченно длины, текст)
o Реплицированные связи (ребра графа)
o Аналоги распределенных внешних ключей (foreign keys)
o Большинство данных распределено случайно
Memcache
Как используется memcached?
* Высокопроизводительная распределенная хэш-таблица
* Содержит «горячие» данные из MySQL
* Снижает нагрузку на уровень баз данных
* Основная форма кэширования
* Используется более 25TB памяти на нескольких тысячах серверов
* Среднее время отклика менее 250 микро-секунд
* Кэшируются сериализованные структуры данных PHP
* Отсутствие автоматического механизма проверки консистенции данных между memcached и MySQL — приходится делать это на уровне программного кода
* Множество multi-get запросов для получения данных на другом конце ребер графа
* Ограниченная модель данных, неэффективен для маленьких объектов
Доработки:
* Порт на 64-битную архитектуру
* Более эффективная сериализация
* Многопоточность
* Улучшенный протокол
* Компрессия
* Проксирование запросов
* Доступ к memcache через UDP:
o уменьшает расход памяти благодаря отсутствию тысяч буферов TCP соединений
o управление ходом исполнения приложение (оптимизация для multi-get)
* Статистика о работе потоков по запросу — уменьшает блокировки
* Ряд изменений в ядре Linux для оптимизации работы memcache:
o распределение управления сетевыми прерывания по всем ядрам
o оппортунистический опрос сетевых интерфейсов
* После вышеперечисленных модификаций memcached способен выполнять до 250 тысяч операций в секунду, по сравнению со стандартными 30-40 тысячами без данных изменений
Thrift
Что это?
* Легкий механизм построения приложений с использованием нескольких языков программирования
* Высокая цель: предоставить механизм прозрачного взаимодействия между языками программирования.
* Предоставляет язык описания интерфейсов, статический генератор кода
* Поддерживаемые языки: C++, PHP, Python, Java, Ruby, Erlang, Perl, Haskell и многие другие
* Транспорты: простой интерфейс для ввода-вывода (сокеты, файлы, буферы в памяти)
* Протоколы: стандарты сериализации (бинарный, JSON)
* Серверы: неблокирующие, асинхронные, как однопоточные, так и многопоточные
Почему именно Thrift?
* Альтернативные технологии: SOAP, CORBA, COM, Pillar, Protocol Buffers — но у всех есть свои существенные недостатки, что вынудило Facebook создать свою технологию
* Он быстрый, очень быстрый
* Меньше рабочего времени тратится каждым разработчиком на сетевые интерфейсы и протоколы
* Разделение труда: работа над высокопроизводительными серверами ведется отдельно от работы над приложениями
* Общий инструментарий, знакомый всем разработчикам
Scribe
Что это?
* Масштабированный распределенный механизм ведения логов
* Перемещает данные с серверов в центральный репозиторий
* Широкая сфера применения:
o Логи поисковых запросов
o Публикации в новостных лентах
o Данные по A/B тестированиям
* Более надежен, чем традиционные системы логгирования, но недостаточно надежен для транзакций баз данных
* Простая модель данных
* Построен на основе Thrift
Хранение фотографий
Сначала сделали это просто:
* Загрузка на сервер: приложение принимает изображение, создает миниатюры в нужных разрешениях, сохраняет в NFS
* Загрузка с сервера: изображения отдаются из NFS через HTTP
* NFS построена на коммерческих продуктах
* Это было необходимо, чтобы сначала проверить, что продукт востребован пользователями и они правда будут активно загружать фотографии
* На самом деле оказалось, что:
o Файловые системы непригодны для работы с большим количеством небольших файлов
o Метаданные не помещаются в оперативную память, что приводит к дополнительным обращениям к дисковой подсистеме
o Ограничивающим фактором является ввод-вывод, а не плотность хранения
Потом начали оптимизировать:
* Кэширование более часто используемых миниатюр изображений в памяти на оригинальных серверах для масштабируемости, надежности и производительности
* Распределение их по CDN для уменьшения сетевых задержек
* Возможно сделать еще лучше:
o Хранение изображений в больших бинарных файлах (blob)
o Сервис, отвечающий за фотографии имеет информацию о том, в каком файле и с каким отступом от начала расположена каждая фотография (по ее идентификатору)
o Этот сервис в Facebook называется Haystack и он оказался в 10 раз эффективнее «простого» подхода и в 3 раза эффективнее «оптимизированного»
Другие сервисы
* SMC: консоль управления сервисами — централизованная конфигурация, определение на какой физической машине работает логический сервис
* ODS: инструмент для визуализации изменений любых статистических данных, имеющихся в системе; удобен для мониторинга и оповещений
* Gatekeeper: разделение развертывания и запуска, A/B тестирования, таргетированный запуск, постепенный запуск
* И еще около 50 других сервисов...
Как это работает все вместе?
Новые альбомы друзей
Facebook Screenshot
1. Получаем профиль по идентификатору пользователя (скорее всего из кэша, но потенциально возможно обращение к базе данных)
2. Получаем список друзей (опять же на основе идентификатора пользователя из кэша или из базы данных в случае промаха)
3. Параллельно запрашиваем идентификаторы последних 10 альбомов для каждого из друзей (multi-get, каждый промах мимо кэша индивидуально вытаскивается из MySQL)
4. Параллельно получаем данные о всех альбомах (на основе идентификаторов альбомов из предыдущего шага)
5. Все данные получены, выполняем логику отрисовки конкретной страницы на PHP
6. Отправляем HTML в браузер, пользователь счастлив
Новостная лента
News Feed Screenshot
News Feed Scheme
Поиск
Search Screenshot
Search Scheme
Подводим итоги
LAMP не идеален
* PHP+MySQL+Memcache решает большинство задач, но не может решить совсем все:
o PHP не может хранить состояния
o PHP не самый производительный язык
o Все данные находятся удаленно
* Facebook разрабатывает собственные внутренние сервисы, чтобы:
o Располагать исполняемый код ближе к данным
o Скомпилированное окружение более эффективно
o Некоторая функциональность присутствует только в других языках программирования
* Философия сервисов:
o Создание сервисов только при необходимости (минимизация издержек по развертке, поддержке и ведению отдельной кодовой базы; потенциальная дополнительная точка сбоя)
o Создание общего набора инструментов для создания сервисов (Thrift, Scribe, ODS, средства мониторинга и уведомлений)
o Использование правильных языка программирования, библиотек и инструментов для решения задачи
* Возвращение инноваций общественности — важный аспект разработки в Facebook:
o Опубликованные свои проекты:
+ Thrift
+ Scribe
+ Tornado
+ Cassandra
+ Varnish
+ Hive
+ xhprof
o Доработки популярных решений:
+ PHP
+ MySQL
+ memcached
o Информация о взаимодействии Facebook с opensource-сообществом, этих и других проектах расположена на странице, посвященной opensource.
* Ключевые моменты культуры разработки в Facebook:
o Двигайся быстро и не бойся ломать некоторые вещи
o Большое влияние маленьких команд
o Будь откровенным и инновационным