Самая большая социальная сеть в рунете наконец-то поделилась информацией о том, как же она работает. Представители проекта в лице Павла Дурова и Олега Илларионова на конференции HighLoad++ ответили на вопросы по разным аспектам работы В контакте, в том числе и техническим. Спешим поделиться итогами их выступления:

Платформа ВКонтакте

  • Debian Linux — основная операционная система
  • nginx — балансировка нагрузки
  • PHP + XCache
  • Apache + mod_php
  • memcached
  • MySQL
  • Собственная СУБД на C, созданная «лучшими умами» России
  • node.js — прослойка для реализации XMPP, живет за HAProxy
  • Изображения отдаются просто с файловой системы xfs
  • ffmpeg — конвертирование видео

Статистика ВКонтакте

  • 95 миллионов учетных записей
  • 40 миллионов активных пользователей во всем мире (сопоставимо с аудиторией интернета в России)
  • 11 миллиардов запросов в день
  • 200 миллионов личных сообщений в день
  • Видеопоток достигает 160Гбит/с
  • Более 10 тысяч серверов, из которых только 32 — фронтенды на nginx (количество серверов с Apache неизвестно)
  • 30-40 разработчиков, 2 дизайнера, 5 системных администраторов, много людей в датацентрах
  • Каждый день выходит из строя около 10 жестких дисков

Архитектура ВКонтакте

Общие принципы ВКонтакте

  • Cервера многофункциональны и используются одновременно в нескольких ролях:

  • Перебрасывание полуавтоматическое
  • Требуется перезапускать daemon’ы
  • Генерация страниц с новостями (микроблоги) происходит очень похожим образом с Facebook (см. Архитектура Facebook), основное отличие — использование собственной СУБД вместо MySQL
  • При балансировке нагрузки используются:
  • Взвешенный round robin внутри системы
  • Разные сервера для разных типов запросов
  • Балансировка на уровне ДНС на 32 IP-адреса
  • Большая часть внутреннего софта написано самостоятельно, в том числе:
    Собственная СУБД (см. ниже)
  • Мониторинг с уведомлением по СМС (Павел сам помогал верстать интерфейс :) )
  • Автоматическая система тестирования кода
  • Анализаторы статистики и логов
  • Мощные сервера:
  • 8-ядерные процессоры Intel (по два на сервер, видимо)
  • 64Гб оперативной памяти
  • 8 жестких дисков (соответственно скорее всего корпуса 2-3U)
  • RAID не используется
  • Не брендированные, собирает компания ТехноОкта
  • Вычислительные мощности серверов используются менее, чем на 20%
  • Сейчас проект расположен в 4 датацентрах в Санкт-Петербурге и Москве, причем:
  • Вся основная база данных располагается в одном датацентре в Санкт-Петербурге
  • В Московских датацентрах только аудио и видео
  • В планах сделать репликацию базы данных в другой датацентр в ленинградской области
  • CDN на данный момент не используется, но в планах есть
  • Резервное копирование данных происходит ежедневно и инкрементально

Волшебная база данных на C ВКонтакте

Этому продукту, пожалуй, уделялось максимум внимания аудитории, но при этом почти никаких подробностей о том, что он собственно говоря собой представляет, так и не было обнародовано. Известно, что:

  • Разработана «лучшими умами» России, победителями олимпиад и конкурсов топкодер; озвучили даже имена этих «героев» Вконтакте (писал на слух и возможно не всех успел, так что извиняйте):

  • Андрей Лопатин
  • Николай Дуров
  • Арсений Смирнов
  • Алексей Левин
  • Используется в огромном количестве сервисов:
  • Личные сообщения
  • Сообщения на стенах
  • Статусы
  • Поиск
  • Приватность
  • Списки друзей
  • Нереляционная модель данных
  • Большинство операций осуществляется в оперативной памяти
  • Интерфейс доступа представляет собой расширенный протокол memcached, специальным образом составленные ключи возвращают результаты сложных запросов (чаще всего специфичных для конкретного сервиса)
  • Хотели бы сделать из данной системы универсальную СУБД и опубликовать под GPL, но пока не получается из-за высокой степени интеграции с остальными сервисами
  • Кластеризация осуществляется легко
  • Есть репликация
  • Если честно, я так и не понял зачем им MySQL с такой штукой — возможно просто как legacy живет со старых времен

Аудио и видео ВКонтакте

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

1000—1500 серверов используется для перекодирования видео, на них же оно и хранится.

XMPP

Как известно, некоторое время назад появилась возможность общаться на Вконтакте через протокол Jabber (он же XMPP). Протокол совершенно открытый и существует масса opensource реализаций.

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

  • Реализован на node.js (выбор обусловлен тем, что JavaScript знают практически все разработчики проекта, а также хороший набор инструментов для реализации задачи)
  • Работа с большими контакт-листами — у многих пользователей количество друзей на вконтакте измеряется сотнями и тысячами
  • Высокая активность смены статусов — люди появляются и исчезают из онлайна чаще, чем в других аналогичных ситуациях
  • Аватарки передаются в base64
  • Тесная интеграция с внутренней системой обмена личными сообщениями Вконтакте
  • 60-80 тысяч человек онлайн, в пике — 150 тысяч
  • HAProxy обрабатывает входящие соединения и используется для балансировки нагрузки и развертывания новых версий
  • Данные хранятся в MySQL (думали о MongoDB, но передумали)
  • Сервис работает на 5 серверах разной конфигурации, на каждом из них работает код на node.js (по 4 процесса на сервер), а на трех самых мощных — еще и MySQL
  • В node.js большие проблемы с использованием OpenSSL, а также течет память
  • Группы друзей в XMPP не связаны с группами друзей на сайте — сделано по просьбе пользователей, которые не хотели чтобы их друзья из-за плеча видели в какой группе они находятся

Интеграция со внешними ресурсами ВКонтакте

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

  • Максимальная кроссбраузерность для виджетов на основе библиотек easyXDM и fastXDM
  • Кросс-постинг статусов в Twitter, реализованный с помощью очередей запросов
  • Кнопка «поделиться с друзьями», поддерживающая openGraph теги и автоматически подбирающая подходящую иллюстрацию (путем сравнивание содержимых тега и атрибутов alt у изображений, чуть ли не побуквенно)</span></li><li><span>Возможность загрузки видео через сторонние видео-хостинги (YouTube, RuTube, Vimeo, и.т.д.), открыты к интеграции с другими</span></li></ul><h2>Интересные факты не по теме ВКонтакте</h2><ul class="listing"><li><span>Процесс разработки близок к Agile, с недельными итерациями</span></li><li><span>Ядро операционной системы модифицированно (на предмет работы с памятью), есть своя пакетная база для Debian</span></li><li><span>Фотографии загружаются на два жестких диска одного сервера одновременно, после чего создается резервная копия на другом сервере</span></li><li><span>Есть много доработок над memcached, в.т.ч. для более стабильного и длительного размещения объектов в памяти; есть даже persistent версия</span></li><li><span>Фотографии не удаляются для минимизации фрагментации</span></li><li><span>Решения о развитии проекта принимают Павел Дуров и Андрей Рогозов, ответственность за сервисы — на них и на реализовавшем его разработчике</span></li><li><span>Павел Дуров откладывал деньги на хостинг с 1 курса :)</span></li></ul><h2>Подводим итоги ВКонтакте</h2><p>В целом Вконтакте развивается в сторону увеличения скорости распространения информацию внутри сети. Приоритеты поменялись в этом направлении достаточно недавно, этим обусловлено, напимер, перенос выхода почтового сервиса Вконтакте, о котором очень активно говорили когда появилась возможность забивать себе текстовые URL вроде vkontakte.ru/ivan.blinkov. Сейчас этот подпроект имеет низкий приоритет и ждет своего часа, когда они смогут предложить что-то более удобное и быстрое, чем Gmail.</p><p>Завеса тайны насчет технической реализации Вконтакте была немного развеяна, но много моментов все же остались секретом. Возможно в будущем появится более детальная информация о собственной СУБД Вконтакте, которая как оказалось является ключом к решению всех самых сложных моментов в масштабируемости системы.</p><p>Как я уже упоминал этот пост написан почти на память, на основе небольшого конспекта «круглого стола Вконтакте», так что хочется сразу извиниться за возможные неточности и недопонимания. Я лишь структурировал хаотичную кучу ответов на вопросы. Буду рад уточнениям и дополнениям.</p> <div id="share2"> <div id="load_share2"></div> </div><style>.wikiTable td td{padding: 0px;border:none;}</style><table class="wikiTable" cellpadding="0" cellspacing="0" style="width:100%;"><tr><td width="50%"><div class="heavy_text">Похожие новости:</div><table cellspacing="0" cellpadding="0" class="r_news"><tbody><tr><td class="r_news_td"> <table width="100%" cellspacing="0" cellpadding="0" border="0"> <tbody><tr><td class="r_news_tmbnl"> <a href="http://www.vknews.ru/novosti/v-kontakte-user-api-bagi-socialnoj-seti/"><img src="http://www.vknews.ru/images/anynews.png"/></a> <td class="r_news_cnt"><a href="http://www.vknews.ru/novosti/v-kontakte-user-api-bagi-socialnoj-seti/">В Контакте User API: баги социальной сети.</a></td></tr> </tbody></table></td></tr><tr><td class="r_news_td"> <table width="100%" cellspacing="0" cellpadding="0" border="0"> <tbody><tr><td class="r_news_tmbnl"> <a href="http://www.vknews.ru/novosti/raznoobrazit-v-kontakte-naibolee-interesnye-prilozheniya-dlya-socialnoj-seti/"><img width="60" height="60" src="http://www.vknews.ru/images/novosti/thumbnail3196-60x60.png" class="attachment-thumbnail wp-post-image" alt="" title=""/></a></td> <td class="r_news_cnt"><a href="http://www.vknews.ru/novosti/raznoobrazit-v-kontakte-naibolee-interesnye-prilozheniya-dlya-socialnoj-seti/">наиболее интересные приложения для социальной сети</a></td></tr> </tbody></table></td></tr><tr><td class="r_news_td"> <table width="100%" cellspacing="0" cellpadding="0" border="0"> <tbody><tr><td class="r_news_tmbnl"> <a href="http://www.vknews.ru/novosti/pereezd-socialnoj-seti-vkontakte/"><img width="60" height="60" src="http://www.vknews.ru/images/novosti/t201106216978g-60x60.jpg" class="attachment-thumbnail wp-post-image" alt="" title=""/></a></td> <td class="r_news_cnt"><a href="http://www.vknews.ru/novosti/pereezd-socialnoj-seti-vkontakte/">Переезд социальной сети ВКонтакте</a></td></tr> </tbody></table></td></tr><tr><td class="r_news_td"> </td></tr></tbody></table></td><td width="50%"><div class="heavy_text">Новости партнеров:</div><div id="load_news"></div></td></tr></table> <div id="load_cntntadvt"></div><div id="load_cmmts"></div> <!--noindex--></div></div></div><div id="load_ftradvt"></div> </div><div id="myLink">Ссылка на эту страницу: <a href="<script language="JavaScript">document.write(location.href)</script>"><script language="JavaScript">document.write(document.title)</script></a></div> </div> </div> </div> <div id="bFooter"> <ul class="bNav"> <li><a href="http://www.vknews.ru/">главная</a></li> <li><a href="http://www.vknews.ru/about/">о сайте</a></li> <li><a href="http://www.vknews.ru/forum/">форум</a></li> <li><a href="http://www.vknews.ru/karta-sajta/">карта сайта</a></li> </ul> </div> <div id="bFooter"> <p><a href="/">Новости ВКонтакте</a> © 2009-2011</p> </div> <div id="bFooter"><p><a href="http://www.liveinternet.ru/click"target="_blank" rel="nofollow"><img src="//counter.yadro.ru/logo?23.10"title="LiveInternet: показано число посетителей за сегодня"alt="" border="0" width="88" height="15"/></a></p></div></div><div style="display:none;"><script type="text/javascript">(function(w, c) {(w[c] = w[c] || []).push(function() { try {w.yaCounter6483220 = new Ya.Metrika({id:6483220,trackLinks:true,accurateTrackBounce:true});}catch(e) { }});})(window, 'yandex_metrika_callbacks');</script></div><script src="//mc.yandex.ru/metrika/watch.js" type="text/javascript" defer="defer"></script><noscript><div><img src="//mc.yandex.ru/watch/6483220" style="position:absolute; left:-9999px;" alt=""/></div></noscript><script type="text/javascript" src="http://www.vknews.ru/js/blocks.js"></script><script type="text/javascript" src="//yandex.st/share/share.js" charset="utf-8"></script><script type="text/javascript" src="http://vkontakte.ru/js/api/share.js?10" charset="windows-1251"></script><script type="text/javascript" src="http://userapi.com/js/api/openapi.js?25"></script><script type="text/javascript">VK.init({apiId: 1967104, onlyWidgets: true});</script><div id="block_share"><script type="text/javascript">share(false)</script><script type="text/javascript">u=location.href.replace(/\/page\/.*?$/,'/');u=u.replace(/\/dynamicwp\//,'/');</script><ul class="share_count"><li><script type="text/javascript">document.write('<a href="http://twitter.com/share" class="twitter-share-button" data-url="'+u+'" data-count="horizontal" data-lang="ru">Tweet</a>');</script><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><script type="text/javascript">document.write(VK.Share.button(u,{type: "round", text: "Сохранить"}));</script></li><li><div id="vk_like"></div><script type="text/javascript">VK.Widgets.Like("vk_like", {type: "button", verb: 1, pageUrl:u});</script></li><li><script type="text/javascript" src="http://rutvit.ru/js/share.js"></script></li></ul></div><script type="text/javascript"> document.getElementById('load_share').appendChild(document.getElementById('block_share')); </script><div id="block_share2"><script type="text/javascript">u=location.href.replace(/\/page\/.*?$/,'/');u=u.replace(/\/dynamicwp\//,'/');</script><ul class="share_count"><li><script type="text/javascript">document.write('<a href="http://twitter.com/share" class="twitter-share-button" data-url="'+u+'" data-count="horizontal" data-lang="ru">Tweet</a>');</script><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></li><li><script type="text/javascript">document.write(VK.Share.button(u,{type: "round", text: "Сохранить"}));</script></li><li><div id="vk_like_2"></div><script type="text/javascript">VK.Widgets.Like("vk_like_2", {type: "button", verb: 1, pageUrl:u});</script></li><li><script type="text/javascript" src="http://rutvit.ru/js/share.js"></script></li></ul><script type="text/javascript">share(false)</script></div><script type="text/javascript"> document.getElementById('load_share2').appendChild(document.getElementById('block_share2')); </script><div id="partner_news"><div id="DIV_DA_18375"></div></div><script type="text/javascript"> document.getElementById('load_news').appendChild(document.getElementById('partner_news')); </script><div id="block_cmmts"><div id="vk_comments"></div><script type="text/javascript"> VK.Widgets.Comments("vk_comments", {limit: 20, width: "605"}); </script></div><script type="text/javascript"> document.getElementById('load_cmmts').appendChild(document.getElementById('block_cmmts')); </script><script>document.getElementById('load_sidebar').innerHTML=block_sidebar();</script><script>document.getElementById('load_cntntadvt').innerHTML=cntntadvt();</script><script>document.getElementById('load_ftradvt').innerHTML=ftradvt();</script><script charset="windows-1251" type="text/javascript" src="http://www.directadvert.ru/show.cgi?adp=18375&div=DIV_DA_18375"></script><script charset="windows-1251" type="text/javascript" src="http://nnn.novoteka.ru/show.cgi?adp=10858&div=DIV_NNN_10858"></script><script charset="windows-1251" type="text/javascript" src="http://nnn.novoteka.ru/show.cgi?adp=10859&div=DIV_NNN_10859"></script><!--/noindex--></body></html>