Сегодня представители Одноклассников рассказали о накопленном за 5 лет опыте по поддержанию высоконагруженного проекта. Была опубликована довольно детальная информация о том, как устроена эта социальная сеть для аудитории "постарше". Далее можно прочитать мою версию материала, либо перейти на оригинал по сссылке .
Платформа
Статистика
- До 2.8 млн. пользователей онлайн в часы пик
- 7,5 миллиардов запросов в день (150 000 запросов в секунду в часы пик)
- 2 400 серверов и систем хранения данных, из которых 150 являются веб-серверами
- Сетевой трафик в час пик: 32 Gb/s
Оборудование
Сервера используются двухпроцессорные с 4 ядрами, объемом памяти от 4 до 48 Гб. В зависимости от роли сервера данные хранятся либо в памяти, либо на дисках, либо на внешних системах хранения данных.
Все оборудование размещено в 3 датацентрах, объединенных в оптическое кольцо. На данный момент на каждом из маршрутов пропускная способность составляет 30Гбит/с. Каждый из маршрутов состоит из физически независимых друг от друга оптоволоконных пар, которые агрегируются в общую “трубу” на корневых маршрутизаторах.
Сеть физически разделена на внутреннюю и внешнюю, разные интерфейсы серверов подключены в разные коммутаторы и работают в разных сетях. По внешней сети HTTP сервера, общаются с Интернетом, по внутренней сети все сервера общаются между собой. Топология внутренней сети – звезда. Сервера подключены в L2 коммутаторы (access switches), которые, в свою очередь, подключены как минимум двумя гигабитными линками к aggregation стеку маршрутизаторов. Каждый линк идет к отдельному коммутатору в стеке. Для того, чтобы эта схема работала, используется протокол RSTP. При необходимости, подключения access коммутаторов к agregation стеку осуществляются более чем двумя линками с использованием link aggregation портов. Aggregation коммутаторы подключены 10Гб линками в корневые маршрутизаторы, которые обеспечивают как связь между датацентрами, так и связь с внешним миром. Используются коммутаторы и маршрутизаторы от компании Cisco.
Для связи с внешним миром используются прямые подключения с несколькими крупнейшими операторами связи, общий сетевой трафик в часы пик доходит до 32Гбит/с.
Архитектура
Архитектура проекта имеет традиционную многоуровневую структуру:
- презентационный уровень;
- уровень бизнес-логики;
- уровень кэширования;
- уровень баз данных;
- уровень инфраструктуры (логирование, конфигурация и мониторинг).
Код проекта в целом написан на Java, но есть исключения в виде модулей для кэширования на C и C++. Java был выбран так как он является удобным языком для разработки, доступно множество наработок в различных сферах, библиотек и opensource проектов.
Презентационный уровень
- Используем собственный фреймворк, позволяющий строить композицию страниц на языке Jаvа, с использованием собственные GUI фабрик (для оформления текста, списков, таблиц и портлетов).
- Страницы состоят из независимых блоков (обычно портлетов), что позволяет обновлять информацию на них частями с помощью AJAX запросов.
- При данном подходе одновременно обеспечивается минимум перезагрузок страниц для пользователей с включенным JavaScript, так и полная работоспособность сайта для пользователей, у которых он отключен.
- Google Web Toolkit используется для реализации функциональные компонент, таких как Сообщения, Обсуждения и Оповещения, а также все динамических элементов (меню шорткатов, метки на фотографиях, сортировка фотографий, ротация подарков и. т.д.). В GWT используются UIBinder и HTMLPanel для создания интерфейсов.
- Кешируются все внешние ресурсы (Expires и Cache-Control заголовки). CSS и JavaScript файлы минимизируются и сжимаются (gzip).
- Для уменьшения количества HTTP запросов с браузера, все JavaScript и CSS файлы объединяются в один. Маленькие графические изображения объединяются в спрайты.
- При загрузке страницы скачиваются только те ресурсы, которые на самом деле необходимы для начала работы.
- Никаких универсальных CSS селекторов. Стараются не использовать типовые селекторы (по имени тэга), что повышает скорость отрисовки страниц внутри браузера.
- Если необходимы CSS expressions, то пишутся "одноразовые". По возможности избегаются фильтры.
- Кешируется обращения к DOM дереву, а так же свойства элементов, приводящие к reflow. Обновляется DOM дерево в "оффлайне".
Уровень бизнес-логики
На уровне бизнес логики располагаются около 25 типов серверов и компонентов, общающихся между собой через удаленные интерфейсы. Каждую секунду происходит около 3 миллионов удаленных запросов между этими модулями. Сервера на уровне бизнес логики разбиты на группы. Каждая группа обрабатывает различные события. Есть механизм маршрутизации событий, то есть любое событие или группу событий можно выделить и направить на обработку на определенную группу серверов. При общении серверов между собой используется свое решение, основанное на JBoss Remoting .
Уровень кэширования
Для кэширования данных используется самописный модуль odnoklassniki-cache. Он предоставляет возможность хранения данных в памяти средствами Java Unsafe. Кэшируются все данные, к которым происходит частое обращение, например: профили пользователей, списки участников сообществ, информация о самих сообществах, граф связей пользователей и групп, праздники, мета информация о фотографиях и многое другое. Для хранения больших объемов данных в памяти используется память Java off heap memory для снятия ненужной нагрузки с сборщика мусора. Кеши могут использовать локальный диск для хранения данных, что превращает их в высокопроизводительный сервер БД. Кеш сервера, кроме обычных операций ключ-значение, могут выполнять запросы по данным, хранящимся в памяти, минимизируют таким образом передачу данных по сети. Используется map-reduce для выполнения запросов и операций на кластере. В особо сложных случаях, например для реализации запросов по социальному графу, используется язык C. Это помогает повысить производительность.
Данные распределяются между кластерами кеш серверов, а также используется репликация партиций для обеспечения надежности. Иногда требования к быстродействию настолько велики, что используются локальные короткоживущие кеши данных полученных с кеш серверов, расположенные непосредственно в памяти серверов бизнес логики.
Для примера, один сервер, кэширующий граф связей пользователей, в час пик может обработать около 16 600 запросов в секунду. Процессоры при этом заняты до 7%, максимальный load average за 5 минут — 1.2. Количество вершин графа - более 85 миллионов, связей 2.5 миллиарда. В памяти граф занимает 30 GB.
Уровень баз данных
Суммарный объем данных без резервирования составляет 160Тб. Используются два решения для хранения данных: MS SQL и BerkeleyDB. Данные хранятся в нескольких копиях, в зависимости от их типа от двух до четырех. Полное резервное копирование всех данных осуществляется раз в сутки, плюс каждые 15 минут делаются резервные копии новых данных. В результате максимально возможная потеря данных составляет 15 минут.
Сервера с MS SQL объединены в failover кластера, при выходе из строя одного из серверов, находящийся в режиме ожидания сервер берет на себя его функции. Общение с MS SQL происходит посредством JDBC драйверов.
Используются как вертикальное, так и горизонтальное разбиение данных, т. е. разные группы таблиц располагаются на разных серверах (вертикальное партиционирование), а данные больших таблицы дополнительно распределяются между серверами (горизонтальное партиционирование). Встроенный в СУБД аппарат партиционирования не используется — весь процесс реализован на уровне бизнес-логики. Распределенные транзакции не используются — всё только в пределах одного сервера. Для обеспечения целостности, связанные данные помещаются на один сервер или, если это невозможно, дополнительно разрабатывается логика обеспечения целостности данных. В запросах к БД не используются JOIN даже среди локальных таблиц для минимизации нагрузки на CPU. Вместо этого используется денормализация данных или JOIN происходят на уровне бизнес сервисов, что позволяет осуществлять JOIN как с данными из баз данных, так и с данными из кэша. При проектировании структуры данных не используются внешние ключи, хранимые процедуры и триггеры. Опять же для снижения потребления вычислительных ресурсов на серверах баз данных. SQL операторы DELETE также используются с осторожностью — это самая тяжелая операция. Данные удаляются чаще всего через маркер: запись сначала отмечается как удаленная, а потом удаляется окончательно с помощью фонового процесса. Широко используются индексы, как обычные, так и кластерные. Последние для оптимизации наиболее высокочастотных запросов в таблицу.
Используется C реализация BerkleyDB версии 4.5. Для работы с BerkleydDB используется своя библиотека, позволяющая организовывать двухнодовые master-slave кластера с использованием родной BDB репликация. Запись происходит только в master, чтение происходит с обеих нод. Данные хранятся в tmpfs, transaction логи сохраняются на дисках. Резервная копия логов делается каждые 15 минут. Сервера одного кластера размещены на разных лучах питания дабы не потерять обе копии одновременно. Помимо прочего, BerkleyDB используется и в роли очереди заданий.
Внутри системы используется взвешенный round robin, а также вертикальное и горизонтальное разбиение данных как на уровне СУБД, так и на уровне кэширования.
В разработке новое решение для хранения данных, так как необходим еще более быстрый и надежный доступ к данным.
Уровень инфраструктуры
Для агрегации статистики используется собственная библиотека, основанная на log4j. Сохраняется такая информация, как количество вызовов, среднее, максимальное и минимальное время выполнения, количество ошибок. Данные сохраняются во временные базы, но раз в минуту данные переносятся из них в общий склад данных (data warehouse), а временные базы очищаются. Сам склад реализован на базе решений от Microsoft: MS SQL 2008 и сиситема генерации отчетов Reporting Services. Он расположен на 13 серверах, находящихся в отдельной от production среде. Некоторые из них отвечают за статистику в реальном времени, а некоторые за ведение и предоставление доступа к архиву. Общий объем статистических данных составляет 13Тб. Планируется внедрение многомерного анализа статистики на основе OLAP.
Управление сервисами происходит через самописную централизованную систему конфигурации. Через веб-интерфейс доступно изменение расположения портлетов, конфигурации кластеров, изменение логики сервисов и прочее. Вся конфигурация сохраняется в базе данных. Каждый из серверов периодически проверяет, есть ли обновления для приложений, которые на нем запущены, и, если есть, применяет их.
Мониторинг логически разделен на две части:
- Мониторинг сервисов и компонентов
- Мониторинг ресурсов, оборудования и сети
Система мониторинга сервисов также самописная и основывается на оперативных данных с упомянутого выше склада. Мониторинг ресурсов и здоровья оборудования же онован на Zabbix, а статистика по использованию ресурсов серверов и сети накапливаетя в Cacti. Для предпринятия мер по устранению чрезвычайных ситуаций работают дежурные, которые следят за всеми основными параметрами. Оповещения о наиболее критичных аномалиях приходят по смс, остальные оповещения отсылаются по емейлу.
Команда
Над проектом работают около 70 технических специалистов:
- 40 разработчиков;
- 20 системных администраторов и инженеров;
- 8 тестеров.
Все разработчики разделены на небольшие команды до 3х человек. Каждая из команд работает автономно и разрабатывает либо какой-то новый сервис, либо работает над улучшением существующих. В каждой команде есть технический лидер или архитектор, который ответственен за архитектуру сервиса, выбор технологий и подходов. На разных этапах к команде могут примыкать дизайнеры, тестеры и системные администраторы.
Разработка ведется итерациями в несколько недель. Как пример жизненного цикла разработки можно привести 3х недельный цикл:
- определение архитектуры;
- разработка, тестирование на компьютерах разработчиков;
- тестирование на pre-production среде, релиз на production среду.
Практически весь новый функционал делается "отключаемым", типичный процесс запуска новой функциональной возможности:
- Функционал разрабатывается и попадает в production релиз;
- Через централизованную систему конфигурации функционал включается для небольшой части пользователей;
- Анализируется статистика активности пользователей, нагрузка на инфраструктуру;
- Если предыдущий этап прошел успешно, функционал включается постепенно для все большей аудитории;
- Если в процессе запуска собранная статистика выглядет неудовлетворительно, либо непозволительно вырастает нагрузка на инфраструктуру, то функционал отключается, анализируются причины, исправляются ошибки, происходит оптимизация и все повторяется с начала.
Подводим итоги
- В отличии от остальных популярных социальных сетей в Одноклассниках используются технологии, рассчитанные в первую очередь на корпоративный рынок, начиная от обоих СУБД и заканчивая операционными системами.
- Во многом этот факт обуславливает комплексный подход к генерации пользовательского интерфейса, не слишком высокую производительность и многие другие особенности этой социальной сети.
- Использование "тяжелых" технологий с самого начала оставило Одноклассники с большим количеством доставшегося по наследству от ранних версий устаревшего кода и купленных давно лицензий на проприетарный софт, которые выступают в роли оков, от которых довольно сложно избавиться.
- Возможно эти факторы и являются одними из основных препятствий на пути к завоеванию большей доли рынка и быстрому развитию платформы как в функциональном, так и техническом плане.