Фильм "Социальная сеть" хорошо иллюстрирует феномен развития Facebook’а, сумевшего за рекордный срок собрать баснословную, немыслимую ранее аудиторию. Однако за кадром осталась еще одна составляющая проекта — то, как он работает изнутри. Его техническое устройство.

Что такое Facebook сейчас? Лучше всего это демонстрируют сухие цифры:

  • 500 000 000 активных пользователей (месячная аудитория);
  • 200 000 000 000 просмотров страниц в месяц;
  • 150 000 000 обращений к кэшу в секунду;
  • 2 000 000 000 000 объектов в кэше;
  • 20 000 000 000 фотографий в 4-х разрешениях. Их хватило бы, чтобы покрыть поверхность земли в 10 слоев — это больше, чем на всех других фоторесурсах вместе взятых;
  • более 1 000 000 000 сообщений в чате каждый день;
  • более 100 000 000 поисковых запросов ежедневно;
  • более 400 000 разработчиков сторонних приложений;
  • около 500 разработчиков и системных администраторов в штате;
  • более 1 000 000 активных пользователей на одного инженера;
  • десятки тысяч серверов, десятки гигабит трафика.

Как же все это работает?

Масштабируемость, простота, открытость

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

  • Операционная система — Linux;
  • основной язык программирования — PHP + надстройка;
  • агрессивное кэширование объектов — memcached;
  • хранилище данных в виде пар "ключ-значение" — MySQL;
  • универсальная система сбора и агрегации данных с рабочих серверов — Scribe.

Балансировщик нагрузки выбирает php-сервер для обработки каждого запроса, где HTML генерируется на основе различных источников (таких как MySQL, memcached) и специализированных сервисов. Таким образом, архитектура Facebook имеет традиционный трехуровневый вид:

  • веб-приложение;
  • распределенный индекс;
  • постоянное хранилище.

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

Что обычно происходит за 20 минут на Facebook?

  • Люди публикуют 1 000 000 ссылок;
  • Отмечают друзей на 1 323 000 фотографий;
  • Приглашают 1 484 000 знакомых на мероприятия;
  • Отправляют 1 587 000 сообщений на стену;
  • Пишут 1 851 000 новых статусов;
  • 2 000 000 пар людей становятся друзьями;
  • Загружается 2 700 000 фотографий;
  • Появляется 10 200 000 комментариев;
  • Отправляется 4 632 000 личных сообщений.

Проект на PHP

Напрашивается вопрос: почему именно PHP? Во многом – просто "исторически сложилось". Он хорошо подходит для веб-разработки, легок в изучении и работе, для программистов доступен огромный ассортимент библиотек. К тому же существует огромное международное сообщество. Из негативных сторон можно назвать высокий расход оперативной памяти и вычислительных ресурсов. Когда объем кода стал слишком велик, к этому списку добавились слабая типизация, линейный рост издержек при подключении дополнительных файлов, ограниченные возможности для статичного анализа и оптимизации. Все это стало создавать большие трудности. По этой причине в Facebook была реализована масса доработок к PHP, в том числе оптимизация байт-кода, улучшения в APC (ленивая загрузка, оптимизация блокировок, "подогрев" кэша) и ряд собственных расширений (клиент memcache, формат сериализации, логи, статистика, мониторинг, механизм асинхронной обработки событий).


Схема формирования новостной ленты

Особого внимания заслуживает проект HipHop – это трансформатор исходного кода из PHP в оптимизированный C++. Принцип простой: разработчики пишут на PHP, который конвертируется в оптимизированный C++. В надстройке реализованы статический анализ кода, определение типов данных, генерация кода и многое другое. Также HipHop облегчает разработку расширений, существенно сокращает расходы оперативной памяти и вычислительных ресурсов. У команды из трех программистов ушло полтора года на разработку этой технологии, в частности была переписана большая часть интерпретатора и многие расширения языка PHP. Сейчас коды HipHop опубликованы под opensource лицензией, пользуйся на здоровье.

Культура разработки Facebook

  • Двигаться быстро и не бояться ломать некоторые вещи;
  • большое влияние маленьких команд;
  • быть откровенным и инновационным;
  • возвращать инновации в opensource сообщество.

Доработки MySQL

Теперь о базе данных. В отличие от подавляющего большинства сайтов, MySQL в Facebook используется как простое хранилище пар "ключ-значение". Большое количество логических баз данных распределено по физическим серверам, но репликация используется только между датацентрами. Балансировка нагрузки осуществляется перераспределением баз данных по машинам. Так как данные распределены практически случайным образом, никакие операции типа JOIN, объединяющие данные из нескольких таблиц, в коде не используются. В этом есть смысл. Ведь наращивать вычислительные мощности намного проще на веб-серверах, чем на серверах баз данных.

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

Использование Memcached

Как известно, memcached — высокопроизводительная распределенная хэш-таблица. Facebook хранит в ней "горячие" данные из MySQL, что существенно снижает нагрузку на уровне баз данных. Используется более 25 Тб (только вдумайся в цифру) оперативной памяти на нескольких тысячах серверов при среднем времени отклика менее 250 мкс. Кэшируются сериализованные структуры данных PHP, причем из-за отсутствия автоматического механизма проверки консистенции данных между memcached и MySQL приходится делать это на уровне программного кода. Основным способом использования memcache является множество multi-get запросов, используемых для получения данных на другом конце ребер графа.

Facebook очень активно занимаются доработкой проекта по вопросам производительности. Большинство из описанных ниже доработок были включены в opensource версию memcached: порт на 64-битную архитектуру, сериализация, многопоточность, компрессия, доступ к memcache через UDP (уменьшает расход памяти благодаря отсутствию тысяч буферов TCP-соединений). В дополнение были внесены некоторые изменения в ядро Linux для оптимизации работы memcache. Насколько это действенно? После вышеперечисленных модификаций memcached способен выполнять до 250 000 операций в секунду по сравнению со стандартными 30 000 — 40 000 в оригинальной версии.

Фреймворк Thrift

Еще одной инновационной разработкой Facebook является проект Thrift. По сути, это механизм построения приложений с использованием нескольких языков программирования. Основная цель — предоставить технологию прозрачного взаимодействия между разными технологиями программирования. Thrift предлагает разработчикам специальный язык описания интерфейсов, статический генератор кода, а также поддерживает множество языков, в том числе C++, PHP, Python, Java, Ruby, Erlang, Perl, Haskell. Возможен выбор транспорта (сокеты, файлы, буферы в памяти) и стандарта сериализации (бинарный, JSON). Поддерживаются различные типы серверов: неблокирующие, асинхронные, как однопоточные, так и многопоточные. Альтернативными технологиями являются SOAP, CORBA, COM, Pillar, Protocol Buffers, но у всех есть свои существенные недостатки, и это вынудило Facebook разработать свою собственную. Важное преимущество Thrift’а заключается в производительности. Он очень и очень быстрый, но даже это не главный его плюс. С появлением Thrift на разработку сетевых интерфейсов и протоколов уходит куда меньше времени. В Facebook технология входит в общий инструментарий, который знаком любому программисту. В частности, благодаря этому, удалось ввести четкое разделение труда: работа над высокопроизводительными серверами теперь ведется отдельно от работы над приложениями. Thrift, как и многие другие разработки Facebook, сейчас находится в открытом доступе.

Возвращение инноваций

Возвращение инноваций общественности — важный аспект разработки в Facebook. Компанией были опубликованы свои проекты: ThriftScribeTornadoCassandraVarnishHivexhprof. Помимо этого были сделаны доработки для PHP, MySQL, memcached.

Информация о взаимодействии Facebook с opensource-сообществом этих и других проектов расположена на странице, посвященной opensource.

Хранение фотографий

Закончив на этом рассказывать об используемых технологиях, хочу привести подробности решения интересной задачки внутри социальной сети, а именно — организации хранения фотографий. Многих фотографий. Громадного количества фотографий. Это довольно интересная история. Сначала фотоальбомы пользователей были организованы по самому тривиальному сценарию:

  • при загрузке на сервер приложение принимает изображение, создает миниатюры в нужных разрешениях, сохраняет в NFS;
  • при загрузке с сервера изображения отдаются напрямую из NFS через HTTP.

Такой простой подход был необходим, чтобы сначала проверить, что продукт востребован пользователями, и они действительно будут активно загружать фотографии. Новая фича, как известно, "поперла". Но на практике оказалось, что файловые системы непригодны для работы с большим количеством небольших файлов. Метаданные не помещаются в оперативную память, что приводит к дополнительным обращениям к дисковой подсистеме. Ограничивающим фактором является ввод-вывод, а не плотность хранения. Первым шагом по оптимизации стало кэширование. Наиболее часто используемые миниатюры изображений кэшировались в памяти на оригинальных серверах для масштабируемости и производительности, а также распределялись по CDN (географически распределенной сетевой инфраструктуре) для уменьшения сетевых задержек. Это дало результат. Позже оказалось, что можно сделать еще лучше. Изображения стали хранить в больших бинарных файлах (blob), предоставляя приложению информацию о том, в каком файле и с каким отступом (по сути, идентификатором) от начала расположена каждая фотография. Такой сервис в Facebook получил название Haystack и оказался в десять раз эффективнее "простого" подхода и в три раза эффективнее "оптимизированного". Как говорится, все гениальное просто!


Принцип работы поиска в Facebook

Подводим итоги

Не секрет, что стек LAMP эффективен и пригоден для создания самых сложных систем, но при этом далеко не идеален. Конечно, PHP+MySQL+Memcache решают большинство задач, но далеко не все. Каждый крупный проект сталкивается с тем, что:

  • PHP не может хранить состояния;
  • PHP не самый производительный язык;
  • все данные находятся удаленно.

Facebook’у (да и любым другим крупным проектам) приходится разрабатывать собственные внутренние сервисы, чтобы компенсировать недостатки основных технологий, перенести исполняемый код ближе к данным, сделать ресурсоемкие части кода более эффективными, реализовать преимущества, которые доступны только в определенных языках программирования. Молниеносная обработка запросов от чудовищного количества пользователей достигается за счет комплексного подхода к распределению запросов по тысячам серверов и непрерывной работе над устранением узких мест в системе. В компании есть много небольших команд с полномочиями принимать важные решения, что в совокупности с короткими циклами разработки позволяет очень быстро двигаться вперед и оперативно решать все проблемы. Результат проверить несложно. Открой facebook.com.

Дополнительный инструментарий

Для управления такой огромной системой в Facebook'е были созданы различные дополнительные сервисы. Всего их более пятидесяти, приведу несколько примеров:

  • SMC (консоль управления сервисами) — централизованная конфигурация, определение, на какой физической машине работает логический сервис;
  • ODS — инструмент для визуализации изменений любых статистических данных, имеющихся в системе — удобен для мониторинга и оповещений;
  • Gatekeeper — разделение процессов развертывания и запуска, A/B-тестирования (метод, позволяющий определить, какая версия страницы лучше уговаривает посетителей совершить то или иное действие).

By Ruslan Novikov

Интернет-предприниматель. Фулстек разработчик. Маркетолог. Наставник.