Upload
ontico
View
130
Download
5
Embed Size (px)
Citation preview
Как мы заставили Druid
работать в Одноклассниках
Юрий Невиницин
ЗАЧЕМ?
Статистика
Менеджеры
Разработчики
Администраторы
• Цели
• Аномалии
• Мониторинг
• Эксперименты
• Запуски
• Без неё никак
Немного цифр
• 350 таблиц
• 50TB
• 12 млрд событий в сутки
• Отставание на полчаса
• 6 секунд
• Цена в миллионы долларов
Постановка задачи
Постановка задачи
• Быстро
• 24x7x365 ( -1 ЦОД )
• Масштабируемо
• Open-source (Java)
Druid
• Быстро
• 24x7x365 ( -1 ЦОД )
• Масштабируемо
• Open-source (Java)
• Предагрегация
• Timeseries, TopN, GroupBy
Альтернативы
• PostgreSQL
• Influx
• Prometheus
• OpenTSDB
• ClickHouse
• Все довольны
• Сэкономили миллионы долларов
• 1 человек
Druid
Событий/сек
Кластер 500 000
Нода 50 000
Таблица 10 000
Druid
Событий/сек
Кластер 500 000 2 300 000
Нода 50 000 275 000
Таблица 10 000 90 000
Druid
MAX
Внешние компоненты
• Storage (Amazon, HDFS, local)
• Metadata DB (MySQL, Postgres, Derby)
• ZooKeeper
• Cache (memcache, local)
Собственные компоненты
• Realtime
• Historical
• Broker
• Coordinator
• Indexing service
DATA
Realtime Segment
StorageMeta
Coordinator Historical
Historical
QUERY
Broker
subquery1 subquery2 subquery3 subquery4
Historical HistoricalRealtime
Отказ MySQL
• Данные копятся в Realtime-нодах
• Пока не кончатся ресурсы
= предсказуемый запас времени
Отказ MySQL
Storage, Coordinator
• Данные копятся в Realtime-нодах
• Пока не кончатся ресурсы
= предсказуемый запас времени
• Cassandra-based DB
• Свежие данные всегда доступны
Отказ ZooKeeper
• Маленький таймаут
• Много данных
• Лавина трафика
• «Нет данных»
Что делать?
Отказ ZooKeeper
• Удалить данные ZK
• Иметь запас памяти в ZK
• Корректно завершать Historical
• Стартовать Historical с паузой
• Убрать ненужные чтения
• Убрать ненужные данные
Что делать?
Загрузка данных
Realtime
• sssMMAP MMAP
Искажение данных
PersistedData
SourcePosition
Загрузка в Realtime
PersistedData
SourcePosition
Потеря
Дубль
Деградация чтения
Загрузка данных
Time Calls Host
10:45 123 web1
10:45 132 web2
10:45 345 api1
10:45 354 api2
10:50 120 web1
10:50 128 web2
10:50 342 api1
10:50 333 api2
Time Calls Host
10:45 123 web1
10:45 132 web2
10:45 345 api1
10:45 354 api2
10:50 120 web1
10:50 128 web2
10:50 342 api1
10:50 333 api2
long[] long[]api1 api2 web1 web2
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]api1 api2 web1 web2
int[]
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
1
1
0
0
1
1
0
0
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
1
1
0
0
1
1
0
0
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
1
1
0
0
1
1
0
0
bitmap1
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
bitmap1bitmap2
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
bitmap1bitmap2bitmap3bitmap4
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
1
1
0
0
1
1
0
0
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
1
1
0
0
1
1
0
0
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
SUM(calls) host = web%, mob%, music%, video%
1
1
0
0
1
1
0
0
5 95
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
Загрузка данных
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
Time Calls Host
10:50 123 2
10:50 132 3
10:50 345 0
10:50 354 1
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
Time Calls Host
10:55 123 2
… … …
api1 api2 web1 web2
0 0 1 0
… … … …
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
Time Calls Host
10:50 123 2
10:50 132 3
10:50 345 0
10:50 354 1
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
Time Calls Host
10:55 123 2
… … …
api1 api2 web1 web2
0 0 1 0
… … … …
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
Time Calls Host
10:50 123 2
10:50 132 3
10:50 345 0
10:50 354 1
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
Time Calls Host
10:55 123 2
… … …
api1 api2 web1 web2
0 0 1 0
… … … …
Деградация чтения
Загрузка данных
• Размер сегмента• Частота сброса на диск
• Использовать Selector
like.photo.main
like.photo.main.favorites
like.photo.main.favorites.widget
like.photo.main.favorites.widget.banner125
like.photo.mainlike.photo.albumlike.photo.grouplike.video.mainlike.video.albumlike.video.grouplike.music.mainlike.music.albumlike.music.group
share.photo.mainshare.photo.albumshare.photo.groupshare.video.mainshare.video.albumshare.video.groupshare.music.mainshare.music.albumshare.music.group
comment.photo.maincomment.photo.albumcomment.photo.groupcomment.video.maincomment.video.albumcomment.video.groupcomment.music.maincomment.music.albumcomment.music.group
SUM(calls) Event = like.%
like.photo.mainlike.photo.albumlike.photo.grouplike.video.mainlike.video.albumlike.video.grouplike.music.mainlike.music.albumlike.music.group
share.photo.mainshare.photo.albumshare.photo.groupshare.video.mainshare.video.albumshare.video.groupshare.music.mainshare.music.albumshare.music.group
comment.photo.maincomment.photo.albumcomment.photo.groupcomment.video.maincomment.video.albumcomment.video.groupcomment.music.maincomment.music.albumcomment.music.group
SUM(calls) Event = like.%
Action
LikeShareComment
Object
PhotoVideoMusic
Place
MainAlbumGroup
SUM(calls) Action = like
Action
LikeShareComment
Object
PhotoVideoMusic
Place
MainAlbumGroup
SUM(calls) Action = like
Time Calls Host
10:45 123 2
10:45 132 3
10:45 345 0
10:45 354 1
10:50 120 2
10:50 128 3
10:50 342 0
10:50 333 1
long[] long[]
api1 api2 web1 web2
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
int[]
1
1
0
0
1
1
0
0
5 95
SUM(calls) Action = like
5 11
100 = +
16 = +
Истинно тяжелый запрос
• 2TB• 74 секунды
• Приоритеты• Надо выставлять в запросе• Работают на уровне очереди
• Отказ MySQL предсказуем• Для ZooKeeper: запас памяти, корректно
завершать Historical, а стартовать с паузой• Realtime не гарантирует exactly-once• Подбор размера сегмента и частоты сброса на
диск• Использовать Selector• Разбивать большое измерение на мелкие• Приоритеты на уровне очереди
Юрий Невиницин[email protected]
Юрий Невиницин[email protected]
Юрий Невиницин[email protected]
Юрий Невиницин[email protected]
Деградация чтения
Загрузка данных
t
N rowsHistorical
Realtime N parts = 1
Деградация чтения
Загрузка данных
t
N rowsHistorical
Realtime N parts = 2
Деградация чтения
Загрузка данных
t
N rowsHistorical
Realtime N parts = 3
Деградация чтения
Загрузка данных
t
N rowsHistorical
Realtime N parts = 30
1 | Область названия раздела
Данные: название источника данных, 2016
74 Слайд с текстом
Подзаголовок
• Далтон Трамбо, один из самых успешных голливудских сценаристов, автор
«Римских каникул» и «Спартака», не подозревал, что черный список
«Hollywood 10» реально существует, пока сам не попал туда и не был навсегда
выкинут из жизни фабрики грез;
• Премьера «Трамбо» состоялась в программе «специальный показ» на
кинофестивале в Торонто в сентябре 2015 года. Выход картины в широкий
прокат состоялся 6 ноября 2015 года.
Данные: название источника данных, 2016
75 Слайд с цифрой
63Подпись
в две строчки
%
Данные: название источника данных, 2016
76 Слайд с двумя цифрами
63Подпись
в две строчки
% 27Подпись
в две строчки
млн
Данные: название источника данных, 2016
77 Изображение с комментарием
Стиль изображений
Зайдите в Quick Styles.
Выберите стиль с тенью
Данные: название источника данных, 2016
78 Вертикальный скриншот Android с комментарием
Скриншот на экране
мобильного телефона
на платформе Android
Вставьте свой скриншот в черное
поле мобильного устройства
Данные: название источника данных, 2016
79 Вертикальный скриншот iOS с комментарием
Скриншот на экране
мобильного телефона
на платформе iOs
Вставьте свой скриншот в черное
поле мобильного устройства
Данные: название источника данных, 2016
80 Горизонтальный скриншот iOS
Данные: название источника данных, 2016
81 Горизонтальный скриншот Android
Данные: название источника данных, 2016
82 Скриншот на экране ноутбука
Скриншот
на экране ноутбука
Вставьте свой скриншот
в черное поле ноутбука
Данные: название источника данных, 2016
83 Таблица
Размещения CRM (руб.) Значение
Промо-баннер (ТГБ под аватаркой) 10000 10000 показов
Промо-посты c охватом на свою группу 10000 23000 показов
Оповещения для вступления в группу 10000 8000 показов
Услуги
Промо-баннер (ТГБ под аватаркой) 10000 16000 показов
Промо-посты c охватом на свою группу 10000 28000 показов
Оповещения для вступления в группу 10000 14000 показов
Промо-баннер (ТГБ под аватаркой) 10000 23000 показов
Промо-посты c охватом на свою группу 10000 1 пост
Оповещения для вступления в группу 10000 23000 показов
Промо-баннер (ТГБ под аватаркой) 10000 Бонус
84 Контакты и полезная информация
Поддержка
партнеров
Отдел
продаж
Блог ОК с информацией
о запусках, событиях и др.
insideok.ru
Лучшие кейсы на базе ОК
за последние годы
awards.insideok.ru
Продуктовые
обновления
ok.ru/gruppa
Официальная
группа ОК
ok.ru/ok