Архитектура Ленты на Одноклассниках
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Архитектура Ленты на Одноклассниках

on

  • 4,818 views

 

Statistics

Views

Total Views
4,818
Views on SlideShare
3,077
Embed Views
1,741

Actions

Likes
1
Downloads
12
Comments
0

9 Embeds 1,741

http://jug.lv 1728
https://twitter.com 3
http://assets.txmblr.com 3
https://www.google.com 2
http://summary 1
http://cloud.feedly.com 1
http://translate.googleusercontent.com 1
https://www.google.lv 1
http://www.google.lv 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Архитектура Ленты на Одноклассниках Presentation Transcript

  • 1. Архитектура Ленты на Одноклассниках Алина Васильева разработчик сервиса Лента Одноклассники alina.vasiljeva@odnoklassniki.ru
  • 2. Одноклассники • Социальный портал • Граф друзей • Аудитория: – 250 млн аккаунтов – 6 млн пользователей онлайн – более 40 млн посетителей в день 1 в среднем 90 друзей 12 групп
  • 3. Лента 2
  • 4. Лента • Один из ключевых сервисов портала • Цели – показ пользователю действий и событий друзей и групп – распространение контента по порталу – стимулирование пользователей создавать контент • Задачи – показ интереснейшего контента максимально большому количеству пользователей – агрегация – группировка – сортировка – выживание в условиях высокой нагрузки 3
  • 5. События • В ленту попадают события более чем 100 разных типов – Фото – Статусы – Дружбы – Классы – Подарки – Игры – Группы – Музыка – Видео – и многое другое... 4 Больше всего добавляется классов к фото По показам лидируют темы из групп
  • 6. Запись и хранение событий • Для достижения цели необходимо записывать и хранить события каждого пользователя • Главная сущность: Feed • Для каждого пользователя нужно хранить List<Feed> 5 class Feed { long createDate; short feedTypeId; Long referenceId; ... }
  • 7. Запись и хранение событий • SQL ? 6 • SELECT, JOIN, COUNT...
  • 8. Нагрузка • В час пик пользователи генерируют 1 миллион событий в 5 минут (>3000 операций записи в секунду) 7 • Запросы ленты конкретного пользователя: >4000 в сек • Запросы общей ленты на главной: >9000 в сек
  • 9. История развития хранилища фидов • SQL решение не рассматривалось изначально – высокая нагрузка – необходима высокая доступность – характер данных, запросов и нагрузки 8
  • 10. История развития хранилища фидов • Oracle Berkeley DB – Key / Value хранилище CP-типа – Key: long feedOwnerId – Value: List<Feed>  byte[] – Хранятся последние N записей (500) 9 • Через ~2 года добавили Voldemort + Tarantool – Key / Value хранилище AP-типа – Хранение данных в памяти – Более высокая производительность – Более высокая доступность – Хранятся последние 30 записей – Использовался одновременно с Berkeley
  • 11. Переход на Cassandra • Причины – Нестабильность Berkeley – Ограничение на объѐм хранимых данных – Упирались в трафик • необходимо пересылать по сети все данные • Преимущества – Высокая доступность, распределѐнность – Масштабирование, восстановление на ходу – Высокая скорость записи – Скорость чтения не зависит от объема – Возможность реализации бизнес-логики 10
  • 12. Cassandra • Хранение данных в Column Family – Row Key – Column Key + Column Value + Timestamp 11
  • 13. Хранение фидов в Cassandra 12
  • 14. Общая картина Feed Proxy - координирующее Java-приложение 13
  • 15. Инфраструктура ленты 14 • Сервера распределены по трѐм дата-центрам Feed Proxy кластер: 21 000 запросов/сек Feed Storage кластер: 120 000 запросов/сек
  • 16. Инфраструктура ленты 15 • Выдерживаем потѐрю целого дата-центра Приложения обновляются путѐм отключения серверов в одном ДЦ Обновление кластера Proxy: 5 минут Обновление кластера Storage: 30 минут
  • 17. Общая лента • Задача – показ ленты событий от всех друзей 16 распространение информации получение информации
  • 18. Общая лента 17
  • 19. Список подписок • При дружбе пользователи добавляются друг к другу в список подписок (ObservedList) • Формируется список друзей, за событиями которых пользователь следит и которые попадают к нему в ленту • Храним список подписок для каждого пользователя 18 class ObservedList { List<ObservedItem> items; ... } class ObservedItem { long feedOwnerId; long lastUserAccessTime; long lastFeedOccurrenceTime; ... }
  • 20. Хранение списка подписок • SQL снова не подходит – 350 добавлений в секунду (18 млн за сутки) – 9000 чтений в секунду – характер данных и запросов • Хранили в Berkeley DB, перешли на Cassandra 19
  • 21. 1. Получаем список подписок из ObservedList 2. По каждой подписке получаем список фидов из Storage 3. Объединяем, сортируем Алгоритм сборки общей ленты [simplified] List<Feed> feeds = new ArrayList<Feed>(); ObservedList observedList = getObservedList(feedFollowerId); for (ObservedItem item: observedList.getItems()){ List<Feed> userFeeds = getFeeds(observedItem.getFeedOwnerId()); feeds.addAll(userFeeds); } Collections.sort(feeds, FEEDS_COMPARATOR); 20 Выполняется на Feed Proxy
  • 22. И опять нагрузка • 9000 запросов получения общей ленты в секунду – даже с учѐтом кэширования на вебе – помним про 90 друзей и 12 групп у пользователей! – 9000 * 102 = 918 000 походов в базу в секунду • Базы данных не в состоянии эффективно обработать такое количество запросов 21 Нужен кеш событий общих лент пользователей
  • 23. Feed Cache • Java-приложение, цель которого получение, хранение и отдача общих лент 22
  • 24. Масштабы Feed Cache • Самое мощное приложение инфраструктуры ленты • 64 сервера, распределѐнные по трѐм дата-центрам • Кол-во запросов: 100 тысяч в секунду (~1500 на сервер) • В кэши входит 100 млн событий в 5 минут • Трафик: 1 Гб/сек – 10 Мб/сек входящего на 1 сервер – 6 Мб/сек исходящего на 1 сервер • Объем хранимых данных: 6 ТБ (в RAM) – ~100 ГБ на 1 сервере – в среднем 100 KБ на пользователя 23
  • 25. Хранение данных в Feed Cache • По ключу идентификатора пользователя хранится список фидов • Длина списка ограничена – 1000 записей, но, бывает, уменьшаем (при повышенной нагрузке) – специальный алгоритм по вытестению данных из кэша – планируем переход на Cassandra 24
  • 26. Хранение данных в Feed Cache • Помимо списка фидов хранятся также дополнительные данные – время последнего логина – время последнего открытия ленты – время последнего обновления данных с Feed Proxy – значение последнего выбранного фильтра • Данные сериализуются и хранятся в Off-Heap памяти • Раз в 12 часов сервер записывает данные на диск (снепшот) • При рестарте приложение стартует со снепшота ~8 минут • При старте без снепшота есть механизмы обеспечивающие плавную загрузку данных 25
  • 27. Кластер Feed Cache 26 • Шардинг – каждый сервер обслуживает 1/64 часть пользователей – партиционирование по id пользователя • У каждого сервера есть «заместитель», на который перенаправляются запросы в случае недоступности • Обновление приложений всего кластера занимает ~1 час (обновление по ¼ серверов)
  • 28. Feed Cache - Отдача данных • Feed Cache запрашивает новые события с Feed Proxy по истечению временного периода (15 минут) – инфраструктура уже выдерживает обновления раз в 1 минуту 27
  • 29. Время последнего события • И всѐ же нагрузка на хранилище фидов получается черезмерно большая • При каждом обновлении на Feed Proxy обходить базы всех друзей неоправданно дорого • ведь новые события могли появиться всего у пары из них, а то вообще ни у кого • Решение - отдельно хранить дату добавления последнего события в ленту пользователя • Отдельная база: Voldemort + Tarantool (key / value) – long feed_owner_id  long last_create_date 28
  • 30. База UpdateInfo • При добавлении нового события обновляется timestamp в базе UpdateInfo • Далее это значение проверяется при сборке событий для общей ленты 29
  • 31. • Перед запросом в базу Feeds проверяется значение UpdateInfo - появились ли новые события Алгоритм сборки общей ленты [improved] 30 public List<Feed> collectRecentFeeds( long feedFollowerId, long lastUpdated){ 1. ПОЛУЧАЕМ СПИСОК ПОДПИСОК (OBSERVED LIST) 2. ДЛЯ КАЖДОЙ ПОДПИСКИ 3. ПРОВЕРЯЕМ UpdateInfo if (hasNewFeeds(item.getId(), lastUpdated)){ 4. ПОЛУЧАЕМ ФИДЫ 5. ДОБАВЛЯЕМ ФИДЫ В ОБЩИЙ СПИСОК } } ... } Хотя в UpdateInfo тоже ходим не каждый раз. Значения кэшируются в ObservedList.
  • 32. Группировка событий • Проблема – повторяющиеся бесполезные события 31
  • 33. Группировка событий • Решение – группировка событий 32 • Исключение событий
  • 34. Группировка событий • Решение – инфраструктура мержеров событий 33 List<Feed> feeds = getFeeds(); for (Merger merger: mergers){ merger.mergeFeeds(feeds); } Длина списка уменьшается на ~25%
  • 35. Приоритеты событий • Проблема – событий много, нужно показать пользователю самое интересное • Решение – подсчѐт весов событий и пересортировка на их основании • Вес подсчитывается при входе события в Feed Cache • Также анализируется состояние кэша – подсчитывется сколько событий каких типов уже присутствует в кэше 34 множество дополнительных коэффициентов и параметров
  • 36. Feed Stats • Отдельное Java-приложение с хранением данных в Cassandra • Сбор статистики о предпочтениях пользователей • Записывает действия, которые пользователь совершает по отношению к своим друзьям – 53 000 записей в секунду • На основании собранной статистики подсчитывает веса друзей • Далее этот вес используется лентой при подсчѐте веса события 35
  • 37. Полная картина 36
  • 38. Real-time доставка событий • Проблема: чтобы увидеть новые события пользователю необходимо обновить страницу • С учѐтом многоуровнего кэширования и ограничений новое событие может прийти в ленту с задержкой • Задача: доставлять события в ленты пользователей моментально и автоматически 37
  • 39. Real-time доставка событий После добавления нового события Feed Storage нотифицирует Feed Cache друзей в онлайне, отсылая им фид, который далее переправляется прямо на Web 38
  • 40. Спасибо! Алина Васильева разработчик сервиса Лента Одноклассники alina.vasiljeva@odnoklassniki.ru odnoklassniki.ru/alina v.ok.ru job@odnoklassniki.ru