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