Как мы заставили Druid работать в Одноклассниках / Юрий...

Preview:

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• Разбивать большое измерение на мелкие• Приоритеты на уровне очереди

Юрий Невиницинnevinitsin@corp.mail.ru

Юрий Невиницинnevinitsin@corp.mail.ru

Юрий Невиницинnevinitsin@corp.mail.ru

Юрий Невиницинnevinitsin@corp.mail.ru

Деградация чтения

Загрузка данных

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 Контакты и полезная информация

Поддержка

партнеров

partners@ok.ru

Отдел

продаж

sales@corp.mail.ru

Блог ОК с информацией

о запусках, событиях и др.

insideok.ru

Лучшие кейсы на базе ОК

за последние годы

awards.insideok.ru

Продуктовые

обновления

ok.ru/gruppa

Официальная

группа ОК

ok.ru/ok

Recommended