SlideShare uma empresa Scribd logo
1 de 30
Baixar para ler offline
Подсчет уникальных
комбинаций на примере
статистики групп в
Одноклассниках
Александр Шарак
Руководитель
отдела статистики
Одноклассников
Задача
• Необходимо посчитать «уники» для отображения на графиках
в разделе «Статистика» для администраторов групп
Задача
• Надо посчитать, сколько у нас уникальных комбинаций такого
типа:
• группа, пол, возраст
• группа, тип активности

• Каждый тип комбинаций надо посчитать за разные периоды:
•
•
•
•
•
•
•

час
6 часов
сутки
текущие 24 часа
последние 7 дней
календарный месяц
последние 365 дней
Типичные ошибки подсчетов
• Данные не должны дублироваться:
• меняется возраст
• меняется место жительства
• меняется пол

• Ну и конечно нельзя просто суммировать данные по дням, чтобы
получить данные за неделю.
Выбор платформы

• Статистика должна быть точной.
• Подсчёты «задним числом» другим алгоритмом.
• Подсчёты должны быть быстрыми, не обязательно в realtime:
• Статистика за текущие 24 часа должна быть готова раз в час (для начала).
• Статистика за закрытые периоды, например 1 астрономический час, должна быть
готова за 15 минут.
• Статистика за последние 365 дней должна быть готова «утром».

• Должна быть возможность запросить новые данные по всем группам
или все данные за любую дату по отдельно взятой группе.
• Подсчёты должны быть экономными.
• Разработка системы должна быть быстрой.
• Данные должны быть доступны для внутреннего анализа.
Наш выбор
• Учитывая:
• требования
• доступные человеческие ресурсы и их компетенцию

• Выбрали:
• MS SQL 2012 Always On availability group

• Некоторые сомнения у нас были, особенно про подсчет
статистики за последние 365 дней.
В SQL всё просто!
• Select groupid, country, count(distinct userid)
from table
where timestamp between @datefrom and @dateto
group by groupid, country
Однако объёмы не маленькие
• Более 400 000 активных групп в день.
• Более 1 000 000 активных групп в год.
• Более 800 000 000 действий в день.

• Для подсчета «уников» за последние 365 дней «тупым
подходом» необходимо обработать более 200 000 000 000
записей каждый день.
Как SQL считает «уники»
• Select groupid, country, gender, count(distinct userid)
from table
where timestamp between @datefrom and @dateto
group by groupid, country, gender
• Алгоритм:
•

Считываются данные по кластерному индексу.

•
•

Данные делятся на столько частей, сколько доступно ядер.
Каждый поток создает хеш-таблицу:
(hash key, (groupid, country, gender, user), count).
Каждый поток из предыдущей хеш-таблицы создает новую:
(hash key, (groupid, county, gender), count).
Хеш-таблицы объединяются и выдается результат.

•
•

• Хеш-таблица для первоначального агрегирования может получиться огромной и
в памяти не уложится.
Как SQL считает «уники» при не
достаточной памяти
• Подсчеты делятся на более мелкие части и промежуточные результаты (хеш -таблицы
скидываются в temp db на диск).
• SQL-сервер делает следующие итерации:
•
•
•
•
•
•
•

считываются данные по кластерному индексу;
данные делятся на столько частей, сколько доступно ядер;
каждый поток создает хеш-таблицу;
если памяти не хватает, то хеш-таблица скидывается на диск и берётся следующая пачка данных;
потом хеш-таблицы считываются с диска и объединяются;
если опять не хватает памяти, то опять всё скидывается на диск;
и так до тех пор, пока не получается результат.

• «Со стороны» это выглядит так:
•
•
•
•

сначала наблюдаются бешеные процессы чтения и высокая нагрузка на CPU;
процессы чтения прекращаются, но нагрузка на CPU все еще высокая;
нагрузка на CPU падает и начинается интенсивная запись на диск;
эти три шага повторяются много раз.

• В результате:
•
•

подсчеты очень медленные;
IO-система так нагружена, что параллельные процессы «проседают».
Упрощаем задачу для SQL
• Необходимо, чтобы селекты укладывались в память
• Самое простое - делим все группы на несколько частей и считаем «уники» для
каждой части отдельно.
•
•

Данные надо хранить с кластеризацией по ID групп, что вызовет проблемы при загрузке – сплошные
вставки и фрагментация. Исторические данные нельзя было бы удалить.
Если данные кластеризовать по дате, то для каждой части придется делать full scan за весь период

•

Делается много лишних операций, описанных ниже

• Для «уников» за большие периоды надо использовать результаты подсчетов за
меньшие периоды, посчитанные ранее, например:
•
•

для подсчета часа использовать минутные «уники»;
для подсчета месяца использовать суточные «уники».
Доставка логов
• На сервере, куда параллельными потоками пишется много
данных, делать серьезные подсчеты невозможно.
• Поставили «буферную» базу для принятия логов и передачи
дальше системе статистики
Система
групп

Буфер

Система
статистики
Выкачка логов из «буфера»
• С большой периодичностью в одном потоке выкачиваем данные
из «буфера».
• Обработку строковых типов не делаем, так как это крайне
неэффективно.
• Преобразование строк в цифровые значение (нормализация
данных) тоже, соответственно, не делаем.
• Получаем только целые числа (ID сущностей) и даты.
COLUMN_NAME

DATA_TYPE

Registered

smalldatetime

ID_Group

bigint

ID_User

bigint

ActionType

tinyint

VisitType

tinyint

MemberType

tinyint
Выкачка логов из «буфера»
• Сделали кластерный индекс по времени события с партициями
по дням.
• Такой индекс нам позволяет быстро записать и прочитать
данные с постепенно возрастающим временем события.
• Время сброса данных растет пропорционально росту активности
в группах, но не пропорционально росту размера всей таблицы.
• Однако данные за один квартал мы храним в отдельной базе:
• чтобы бэкапы происходили «быстро»;
• чтобы «старые» данные можно было эффективно убрать в архив.
Как передать результаты обратно
на сайт
• Full dump:
•

легко реализовать;

•

годится только для небольшого объёма данных.

• По changetime:
•
•
•

трудно отследить удаления (например, когда в группе всего один пользователь и он стал старше);
если изменилась одна запись в группе, то надо пометить все связанные;
постоянный апдейт колонки changetime и деградация индекса.

• Лента изменений:
•
•
•

в ленту идут только инсерты;
удаления отслеживать не надо;
сайт получает полный комплект измененных статистик, которым можно заменить старый комплект без
дополнительно обработки.
Топология
Система
групп

Буфер

Буфер
резерв
•

MS SQL Server
•
•
•
•

80 GB RAM
2 CPU (6 ядер) (мощные)
Temp db – SAS-диски
Данные – массив из SATA-дисков

MS SQL
Primary

MS SQL
Secondary
(mirror)
Big Fail
• Сначала всё, как обычно, работало достаточно быстро.
• Но со временем система начала все больше тормозить:
•
•
•
•

группы стали популярнее;
расчеты стали немного сложнее;
данных за большие периоды накапливалось все больше (особенно для подсчета последних 365 дней);
подсчеты «уников» за большие периоды так начали нагружать IO, что начали проседать
параллельные процессы загрузки данных и подсчеты маленьких периодов.

• Поэтому мы решили, что MS SQL secondary (mirror), который доступен в режиме
read only, должен заняться полезным делом:
•

Сделали так, чтобы сервис забирал результаты не с primary, а с secondary сервера.

• В результате:
•

нагрузка на IO систему сильно снизилась.
Big Fail

•

И всё равно надо было предпринимать шаги по масштабированию, так как мы понимали, что долго так не
протянем.
О масштабируемости
• Масштабируется MS SQL AlwaysOn HA group легко:
•

можно добавить в кластер secondary сервера для подсчетов.

• Но это дорого стоит.
• Мы начали думать: можем ли мы посчитать «уники» за большие периоды
эффективней, чем MS SQL?
• Тогда мы бы могли в MS SQL оставить только то, что хорошо и быстро работает:
•
•
•

хранилище для исходных данных;
хранилище для результатов;
подсчеты «уников» за маленькие периоды – до часа.
Эффективный алгоритм
• Мы придумали быстрый алгоритм, как при помощи Merge Sorta файлов
посчитать «уники», нагружая IO и CPU по максимуму, при этом делая минимум
лишних операций и используя минимум памяти.
• Далее рассмотрим частный случай, когда мы из семи дневных результатов
высчитываем недельные «уники».
Выгрузка данных в файлы
• Из базы данных в память выкачиваем данные за последний закрытый период
(например, день), отсортированные по (groupid, userid).
• Записываем эти данные в 100 файлов, распределяя по groupid mod 100, чтобы
все записи одной группы попали только в один файл. Это необходимо для
распараллеливания.
• Формат файлов – бинарный, чтобы мы могли четко знать. где именно начинается
и заканчивать одна запись.
•

Мы пробовали использовать json и csv форматы но сразу от них отказались, потому что на парсинг
этих файлов уходила львиная доля мощностей CPU.

• Исходные данные в таком формате:
•
•
•

За один день – 3 Gb
За 7 дней – 21 Gb
За 365 дней – 1.1 Tb
день
#1

день
#2

день
#3

день
#4

день
#5

день
#6

день
#7

каждый файл отдельно уже отсортирован по ID_Group, ID_User

(1x вначале) сортируем список открытых файлов по ID_Group, ID_User первой считанной записи
(дальше в цикле) отдаем дальше запись с наименьшим ID_Group, ID_User
берем следующую запись из того файла, чья запись «ушла»
перемещаем файл в списке файлов на место, соответствующее следующей считанной записи
Отсортированный список всех данных по ID_Group, ID_User
Накопленные данные
за предыдущую группу
можно считать
готовыми, когда
начинаются данные
про следующую группу

ID_Group

ID_User

ActionType

G1

U1

7

G1

U1

7

G1

U2

5

G2

U2

G2

U3

данные про поведение
конкретного пользователя в
рамках конкретной групы
Распараллеливаем
• Данный алгоритм работает только в одном потоке, то есть, на одном ядре.
• Поэтому мы и создавали не 7 файлов, а 100 комплектов по 7 файлов,
распределяя по groupid mod 100.
• И запустили подсчеты в столько потоков, сколько было ядер на сервере – 24.
• Каждый поток обрабатывал отдельный комплект файлов.

• После завершения подсчетов все результаты записываем (bulk insert) в MS SQL
для передачи далее в «прод».
• А выгруженные файлы не удаляем, а оставляем для подсчетов следующих
периодов, но не дольше 365 дней.

• «Уники» за 7 дней высчитываем за 3 минуты.
Топология
Система
групп

Буфер

Буфер
резерв

•

MS SQL
Primary

MS SQL
Secondary
(mirror)

.NET
«уники»

.NET
«уники»

Два .NET сервера для «уников» - для HA. Оба делают одно и то же.
Нагрузка на CPU

•

CPU не нагружен на 100% потому, что есть дисковая очередь.
Ускоряем ещё больше
• Днем, когда сервер отдыхает, можем высчитывать агрегат за 364 дня. Потом
после полуночи надо будет сделать Merge Sort всего двум файлам. Ускорим в 5
раз.
• Для подсчетов «уников» за последние 364 дня можно использовать комбинацию
дневных и месячных агрегатов. Ускорим на 25%.
• Для подсчетов можем использовать оба .NET сервера (первый сначала
подсчитывает чётные группы, второй – нечётные). Ускорим в два раза.
Tips and Tricks
• Для подсчета «уников» за 365 дней нам надо открыть много файлов – 365x24
(число ядер). Необходимо под каждый FileHandle выделять такой размер буфера,
чтобы он не превышал некую MagicConstant (~1Gb). Иначе Windows Server
начинает делать swap памяти.
• Файлы, в которых храним числовую (IDs) информацию в бинарном виде, не стоит
пытаться зиповать.

• Если шедулируете подсчеты, используя Windows Task Scheduler, то по умолчанию
у тасков стоит низкий приоритет на ресурсы. Через UI его повысить нельзя –
надо экспортировать XML дефиницию таска, повысить в нем соответствующую
настройку и импортировать обратно.
Итоги
• Мы вынесли подсчеты из MS SQL и используем его только как хранилище. К тому
же используем не оптимально, так как нам надо, чтобы данные можно было бы
хранить с кластеризацией по (groupid, userid).
• То есть использование MS SQL не обосновано. Вместо него мы будем
использовать или Open Source базы, или переделаем всё на обработку файлов в
.NET.

• .NET и Windows Server 2008 R2 показал себя как хорошая платформа для
обработки данных и файлов
•
•
•

быстрая и стабильная
с хорошим файл-кешем
удобный язык программирования для аппликации параллельной обработки информации.
Итоги
• «Уники» за 365 дней мы можем посчитать за 4 часа на одном сервере, а
потенциально можем посчитать менее чем за час.
• Это в десятки раз быстрее, чем может MS SQL.
• Подсчеты за меньшие периоды занимают несущественное время.
• Количество серверов, необходимых для подсчетов – 2 (+2 для HA).

• Количество трудозатрат – 3 человеко-месяца.
• А если делать сразу всё правильно – 1 человеко-месяц.
Спасибо за
внимание!
Александр Шарак
Руководитель отдела статистики
Одноклассники
aleksandr.sharak@odnoklassniki.ru

Mais conteúdo relacionado

Mais procurados

ClickHouse: очень быстро и очень удобно / Виктор Тарнавский, Алексей Миловидо...
ClickHouse: очень быстро и очень удобно / Виктор Тарнавский, Алексей Миловидо...ClickHouse: очень быстро и очень удобно / Виктор Тарнавский, Алексей Миловидо...
ClickHouse: очень быстро и очень удобно / Виктор Тарнавский, Алексей Миловидо...
Ontico
 
CodeFest 2014. Бартунов О. — Hstore — документо-ориентированное хранилище и д...
CodeFest 2014. Бартунов О. — Hstore — документо-ориентированное хранилище и д...CodeFest 2014. Бартунов О. — Hstore — документо-ориентированное хранилище и д...
CodeFest 2014. Бартунов О. — Hstore — документо-ориентированное хранилище и д...
CodeFest
 
Александр Соловьёв, Griddynamics.com
Александр Соловьёв, Griddynamics.comАлександр Соловьёв, Griddynamics.com
Александр Соловьёв, Griddynamics.com
Ontico
 
Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)
Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)
Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)
Ontico
 
Что нужно знать об архитектуре ClickHouse / Алексей Зателепин (Яндекс)
Что нужно знать об архитектуре ClickHouse / Алексей Зателепин (Яндекс)Что нужно знать об архитектуре ClickHouse / Алексей Зателепин (Яндекс)
Что нужно знать об архитектуре ClickHouse / Алексей Зателепин (Яндекс)
Ontico
 
Aлександр Зайцев, LifeStreet
Aлександр Зайцев, LifeStreetAлександр Зайцев, LifeStreet
Aлександр Зайцев, LifeStreet
Ontico
 
MongoDB в продакшен - миф или реальность?
MongoDB в продакшен - миф или реальность?MongoDB в продакшен - миф или реальность?
MongoDB в продакшен - миф или реальность?
Alexey Tokar
 
2014.12.23 Николай Самохвалов, Ещё раз о JSON(b) в PostgreSQL 9.4
2014.12.23 Николай Самохвалов, Ещё раз о JSON(b) в PostgreSQL 9.42014.12.23 Николай Самохвалов, Ещё раз о JSON(b) в PostgreSQL 9.4
2014.12.23 Николай Самохвалов, Ещё раз о JSON(b) в PostgreSQL 9.4
Nikolay Samokhvalov
 

Mais procurados (20)

ClickHouse
ClickHouseClickHouse
ClickHouse
 
ClickHouse: очень быстро и очень удобно / Виктор Тарнавский, Алексей Миловидо...
ClickHouse: очень быстро и очень удобно / Виктор Тарнавский, Алексей Миловидо...ClickHouse: очень быстро и очень удобно / Виктор Тарнавский, Алексей Миловидо...
ClickHouse: очень быстро и очень удобно / Виктор Тарнавский, Алексей Миловидо...
 
CodeFest 2014. Бартунов О. — Hstore — документо-ориентированное хранилище и д...
CodeFest 2014. Бартунов О. — Hstore — документо-ориентированное хранилище и д...CodeFest 2014. Бартунов О. — Hstore — документо-ориентированное хранилище и д...
CodeFest 2014. Бартунов О. — Hstore — документо-ориентированное хранилище и д...
 
Gobblin как ETL-фреймворк / Иван Ахлестин (Rambler&Co)
Gobblin как ETL-фреймворк / Иван Ахлестин (Rambler&Co)Gobblin как ETL-фреймворк / Иван Ахлестин (Rambler&Co)
Gobblin как ETL-фреймворк / Иван Ахлестин (Rambler&Co)
 
Выбор NoSQL базы данных для вашего проекта: "Не в свои сани не садись"
Выбор NoSQL базы данных для вашего проекта: "Не в свои сани не садись"Выбор NoSQL базы данных для вашего проекта: "Не в свои сани не садись"
Выбор NoSQL базы данных для вашего проекта: "Не в свои сани не садись"
 
Александр Соловьёв, Griddynamics.com
Александр Соловьёв, Griddynamics.comАлександр Соловьёв, Griddynamics.com
Александр Соловьёв, Griddynamics.com
 
High load++2016.highlights (dropbox+clickhouse)
High load++2016.highlights (dropbox+clickhouse)High load++2016.highlights (dropbox+clickhouse)
High load++2016.highlights (dropbox+clickhouse)
 
Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)
Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)
Переезжаем на Yandex ClickHouse / Александр Зайцев (LifeStreet)
 
Простая и дешёвая бизнес-аналитика на базе Google BigQuery / Алексей Паршуков...
Простая и дешёвая бизнес-аналитика на базе Google BigQuery / Алексей Паршуков...Простая и дешёвая бизнес-аналитика на базе Google BigQuery / Алексей Паршуков...
Простая и дешёвая бизнес-аналитика на базе Google BigQuery / Алексей Паршуков...
 
Pulsedb — система хранения временных рядов
Pulsedb — система хранения временных рядовPulsedb — система хранения временных рядов
Pulsedb — система хранения временных рядов
 
Что нужно знать об архитектуре ClickHouse / Алексей Зателепин (Яндекс)
Что нужно знать об архитектуре ClickHouse / Алексей Зателепин (Яндекс)Что нужно знать об архитектуре ClickHouse / Алексей Зателепин (Яндекс)
Что нужно знать об архитектуре ClickHouse / Алексей Зателепин (Яндекс)
 
Clickhouse
ClickhouseClickhouse
Clickhouse
 
NewSQL: SQL никуда не уходит / Константин Осипов (tarantool.org)
NewSQL: SQL никуда не уходит / Константин Осипов (tarantool.org)NewSQL: SQL никуда не уходит / Константин Осипов (tarantool.org)
NewSQL: SQL никуда не уходит / Константин Осипов (tarantool.org)
 
Опыт использования Spark, Основано на реальных событиях
Опыт использования Spark, Основано на реальных событияхОпыт использования Spark, Основано на реальных событиях
Опыт использования Spark, Основано на реальных событиях
 
Aлександр Зайцев, LifeStreet
Aлександр Зайцев, LifeStreetAлександр Зайцев, LifeStreet
Aлександр Зайцев, LifeStreet
 
MongoDB в продакшен - миф или реальность?
MongoDB в продакшен - миф или реальность?MongoDB в продакшен - миф или реальность?
MongoDB в продакшен - миф или реальность?
 
Мобильная Яндекс.Почта — Дмитрий Александров
Мобильная Яндекс.Почта — Дмитрий АлександровМобильная Яндекс.Почта — Дмитрий Александров
Мобильная Яндекс.Почта — Дмитрий Александров
 
2014.12.23 Николай Самохвалов, Ещё раз о JSON(b) в PostgreSQL 9.4
2014.12.23 Николай Самохвалов, Ещё раз о JSON(b) в PostgreSQL 9.42014.12.23 Николай Самохвалов, Ещё раз о JSON(b) в PostgreSQL 9.4
2014.12.23 Николай Самохвалов, Ещё раз о JSON(b) в PostgreSQL 9.4
 
Поиск наизнанку
Поиск наизнанкуПоиск наизнанку
Поиск наизнанку
 
2014.10.15 блиц-доклад PostgreSQL kNN search
2014.10.15 блиц-доклад PostgreSQL kNN search2014.10.15 блиц-доклад PostgreSQL kNN search
2014.10.15 блиц-доклад PostgreSQL kNN search
 

Semelhante a Александр Шарак, "Одноклассники"

Near-realtime аналитика событий в высоконагруженном проекте / Александр Краше...
Near-realtime аналитика событий в высоконагруженном проекте / Александр Краше...Near-realtime аналитика событий в высоконагруженном проекте / Александр Краше...
Near-realtime аналитика событий в высоконагруженном проекте / Александр Краше...
Ontico
 
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Ontico
 
Применение статистических методов и инструментов для анализа производительнос...
Применение статистических методов и инструментов для анализа производительнос...Применение статистических методов и инструментов для анализа производительнос...
Применение статистических методов и инструментов для анализа производительнос...
Ontico
 
Monitoring driven эксплуатация / Николай Сивко (HeadHunter)
Monitoring driven эксплуатация / Николай Сивко (HeadHunter)Monitoring driven эксплуатация / Николай Сивко (HeadHunter)
Monitoring driven эксплуатация / Николай Сивко (HeadHunter)
Ontico
 
High Load 2009 Dimaa Rus Ready
High Load 2009 Dimaa Rus ReadyHigh Load 2009 Dimaa Rus Ready
High Load 2009 Dimaa Rus Ready
HighLoad2009
 
Дмитрий Куликовский, Алексей Лавренюк - Построение кластеров, нагрузочное тес...
Дмитрий Куликовский, Алексей Лавренюк - Построение кластеров, нагрузочное тес...Дмитрий Куликовский, Алексей Лавренюк - Построение кластеров, нагрузочное тес...
Дмитрий Куликовский, Алексей Лавренюк - Построение кластеров, нагрузочное тес...
Yandex
 
Дмитрий Куликовский - Построение кластеров, нагрузочное тестирование, capacit...
Дмитрий Куликовский - Построение кластеров, нагрузочное тестирование, capacit...Дмитрий Куликовский - Построение кластеров, нагрузочное тестирование, capacit...
Дмитрий Куликовский - Построение кластеров, нагрузочное тестирование, capacit...
Yandex
 

Semelhante a Александр Шарак, "Одноклассники" (20)

Загрузка больших объемов данных для бизнес-аналитики
Загрузка больших объемов данных для бизнес-аналитикиЗагрузка больших объемов данных для бизнес-аналитики
Загрузка больших объемов данных для бизнес-аналитики
 
Как считать и анализировать сотни гигабит трафика в секунду, Станислав Николо...
Как считать и анализировать сотни гигабит трафика в секунду, Станислав Николо...Как считать и анализировать сотни гигабит трафика в секунду, Станислав Николо...
Как считать и анализировать сотни гигабит трафика в секунду, Станислав Николо...
 
Построение системы аналитики
Построение системы аналитикиПостроение системы аналитики
Построение системы аналитики
 
Диагностика postgresql для системного администратора
Диагностика postgresql для системного администратораДиагностика postgresql для системного администратора
Диагностика postgresql для системного администратора
 
Near-realtime аналитика событий в высоконагруженном проекте / Александр Краше...
Near-realtime аналитика событий в высоконагруженном проекте / Александр Краше...Near-realtime аналитика событий в высоконагруженном проекте / Александр Краше...
Near-realtime аналитика событий в высоконагруженном проекте / Александр Краше...
 
Near-realtime аналитика событий в высоконагруженном проекте
Near-realtime аналитика событий в высоконагруженном проектеNear-realtime аналитика событий в высоконагруженном проекте
Near-realtime аналитика событий в высоконагруженном проекте
 
Near-realtime аналитика событий в высоконагруженном проекте
Near-realtime аналитика событий в высоконагруженном проектеNear-realtime аналитика событий в высоконагруженном проекте
Near-realtime аналитика событий в высоконагруженном проекте
 
Near-realtime аналитика событий в высоконагруженном проекте
Near-realtime аналитика событий в высоконагруженном проектеNear-realtime аналитика событий в высоконагруженном проекте
Near-realtime аналитика событий в высоконагруженном проекте
 
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
 
Применение статистических методов и инструментов для анализа производительнос...
Применение статистических методов и инструментов для анализа производительнос...Применение статистических методов и инструментов для анализа производительнос...
Применение статистических методов и инструментов для анализа производительнос...
 
Monitoring driven эксплуатация / Николай Сивко (HeadHunter)
Monitoring driven эксплуатация / Николай Сивко (HeadHunter)Monitoring driven эксплуатация / Николай Сивко (HeadHunter)
Monitoring driven эксплуатация / Николай Сивко (HeadHunter)
 
Monitoring-driven эксплуатация (rootconf2015)
Monitoring-driven эксплуатация (rootconf2015)Monitoring-driven эксплуатация (rootconf2015)
Monitoring-driven эксплуатация (rootconf2015)
 
High Load 2009 Dimaa Rus Ready
High Load 2009 Dimaa Rus ReadyHigh Load 2009 Dimaa Rus Ready
High Load 2009 Dimaa Rus Ready
 
От Статистики до Статистики. Эволюция архитектуры системы на примере системы ...
От Статистики до Статистики. Эволюция архитектуры системы на примере системы ...От Статистики до Статистики. Эволюция архитектуры системы на примере системы ...
От Статистики до Статистики. Эволюция архитектуры системы на примере системы ...
 
HighLoad systems: tips & tricks
HighLoad systems: tips & tricksHighLoad systems: tips & tricks
HighLoad systems: tips & tricks
 
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...
 
Обзор перспективных баз данных для highload / Юрий Насретдинов
Обзор перспективных баз данных для highload / Юрий НасретдиновОбзор перспективных баз данных для highload / Юрий Насретдинов
Обзор перспективных баз данных для highload / Юрий Насретдинов
 
Дмитрий Куликовский, Алексей Лавренюк - Построение кластеров, нагрузочное тес...
Дмитрий Куликовский, Алексей Лавренюк - Построение кластеров, нагрузочное тес...Дмитрий Куликовский, Алексей Лавренюк - Построение кластеров, нагрузочное тес...
Дмитрий Куликовский, Алексей Лавренюк - Построение кластеров, нагрузочное тес...
 
Дмитрий Куликовский - Построение кластеров, нагрузочное тестирование, capacit...
Дмитрий Куликовский - Построение кластеров, нагрузочное тестирование, capacit...Дмитрий Куликовский - Построение кластеров, нагрузочное тестирование, capacit...
Дмитрий Куликовский - Построение кластеров, нагрузочное тестирование, capacit...
 
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
Асинхронная репликация без цензуры, Олег Царёв (Mail.ru Group)
 

Mais de Ontico

Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Ontico
 

Mais de Ontico (20)

One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
 
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
 

Александр Шарак, "Одноклассники"

  • 1. Подсчет уникальных комбинаций на примере статистики групп в Одноклассниках Александр Шарак Руководитель отдела статистики Одноклассников
  • 2. Задача • Необходимо посчитать «уники» для отображения на графиках в разделе «Статистика» для администраторов групп
  • 3. Задача • Надо посчитать, сколько у нас уникальных комбинаций такого типа: • группа, пол, возраст • группа, тип активности • Каждый тип комбинаций надо посчитать за разные периоды: • • • • • • • час 6 часов сутки текущие 24 часа последние 7 дней календарный месяц последние 365 дней
  • 4. Типичные ошибки подсчетов • Данные не должны дублироваться: • меняется возраст • меняется место жительства • меняется пол • Ну и конечно нельзя просто суммировать данные по дням, чтобы получить данные за неделю.
  • 5. Выбор платформы • Статистика должна быть точной. • Подсчёты «задним числом» другим алгоритмом. • Подсчёты должны быть быстрыми, не обязательно в realtime: • Статистика за текущие 24 часа должна быть готова раз в час (для начала). • Статистика за закрытые периоды, например 1 астрономический час, должна быть готова за 15 минут. • Статистика за последние 365 дней должна быть готова «утром». • Должна быть возможность запросить новые данные по всем группам или все данные за любую дату по отдельно взятой группе. • Подсчёты должны быть экономными. • Разработка системы должна быть быстрой. • Данные должны быть доступны для внутреннего анализа.
  • 6. Наш выбор • Учитывая: • требования • доступные человеческие ресурсы и их компетенцию • Выбрали: • MS SQL 2012 Always On availability group • Некоторые сомнения у нас были, особенно про подсчет статистики за последние 365 дней.
  • 7. В SQL всё просто! • Select groupid, country, count(distinct userid) from table where timestamp between @datefrom and @dateto group by groupid, country
  • 8. Однако объёмы не маленькие • Более 400 000 активных групп в день. • Более 1 000 000 активных групп в год. • Более 800 000 000 действий в день. • Для подсчета «уников» за последние 365 дней «тупым подходом» необходимо обработать более 200 000 000 000 записей каждый день.
  • 9. Как SQL считает «уники» • Select groupid, country, gender, count(distinct userid) from table where timestamp between @datefrom and @dateto group by groupid, country, gender • Алгоритм: • Считываются данные по кластерному индексу. • • Данные делятся на столько частей, сколько доступно ядер. Каждый поток создает хеш-таблицу: (hash key, (groupid, country, gender, user), count). Каждый поток из предыдущей хеш-таблицы создает новую: (hash key, (groupid, county, gender), count). Хеш-таблицы объединяются и выдается результат. • • • Хеш-таблица для первоначального агрегирования может получиться огромной и в памяти не уложится.
  • 10. Как SQL считает «уники» при не достаточной памяти • Подсчеты делятся на более мелкие части и промежуточные результаты (хеш -таблицы скидываются в temp db на диск). • SQL-сервер делает следующие итерации: • • • • • • • считываются данные по кластерному индексу; данные делятся на столько частей, сколько доступно ядер; каждый поток создает хеш-таблицу; если памяти не хватает, то хеш-таблица скидывается на диск и берётся следующая пачка данных; потом хеш-таблицы считываются с диска и объединяются; если опять не хватает памяти, то опять всё скидывается на диск; и так до тех пор, пока не получается результат. • «Со стороны» это выглядит так: • • • • сначала наблюдаются бешеные процессы чтения и высокая нагрузка на CPU; процессы чтения прекращаются, но нагрузка на CPU все еще высокая; нагрузка на CPU падает и начинается интенсивная запись на диск; эти три шага повторяются много раз. • В результате: • • подсчеты очень медленные; IO-система так нагружена, что параллельные процессы «проседают».
  • 11. Упрощаем задачу для SQL • Необходимо, чтобы селекты укладывались в память • Самое простое - делим все группы на несколько частей и считаем «уники» для каждой части отдельно. • • Данные надо хранить с кластеризацией по ID групп, что вызовет проблемы при загрузке – сплошные вставки и фрагментация. Исторические данные нельзя было бы удалить. Если данные кластеризовать по дате, то для каждой части придется делать full scan за весь период • Делается много лишних операций, описанных ниже • Для «уников» за большие периоды надо использовать результаты подсчетов за меньшие периоды, посчитанные ранее, например: • • для подсчета часа использовать минутные «уники»; для подсчета месяца использовать суточные «уники».
  • 12. Доставка логов • На сервере, куда параллельными потоками пишется много данных, делать серьезные подсчеты невозможно. • Поставили «буферную» базу для принятия логов и передачи дальше системе статистики Система групп Буфер Система статистики
  • 13. Выкачка логов из «буфера» • С большой периодичностью в одном потоке выкачиваем данные из «буфера». • Обработку строковых типов не делаем, так как это крайне неэффективно. • Преобразование строк в цифровые значение (нормализация данных) тоже, соответственно, не делаем. • Получаем только целые числа (ID сущностей) и даты. COLUMN_NAME DATA_TYPE Registered smalldatetime ID_Group bigint ID_User bigint ActionType tinyint VisitType tinyint MemberType tinyint
  • 14. Выкачка логов из «буфера» • Сделали кластерный индекс по времени события с партициями по дням. • Такой индекс нам позволяет быстро записать и прочитать данные с постепенно возрастающим временем события. • Время сброса данных растет пропорционально росту активности в группах, но не пропорционально росту размера всей таблицы. • Однако данные за один квартал мы храним в отдельной базе: • чтобы бэкапы происходили «быстро»; • чтобы «старые» данные можно было эффективно убрать в архив.
  • 15. Как передать результаты обратно на сайт • Full dump: • легко реализовать; • годится только для небольшого объёма данных. • По changetime: • • • трудно отследить удаления (например, когда в группе всего один пользователь и он стал старше); если изменилась одна запись в группе, то надо пометить все связанные; постоянный апдейт колонки changetime и деградация индекса. • Лента изменений: • • • в ленту идут только инсерты; удаления отслеживать не надо; сайт получает полный комплект измененных статистик, которым можно заменить старый комплект без дополнительно обработки.
  • 16. Топология Система групп Буфер Буфер резерв • MS SQL Server • • • • 80 GB RAM 2 CPU (6 ядер) (мощные) Temp db – SAS-диски Данные – массив из SATA-дисков MS SQL Primary MS SQL Secondary (mirror)
  • 17. Big Fail • Сначала всё, как обычно, работало достаточно быстро. • Но со временем система начала все больше тормозить: • • • • группы стали популярнее; расчеты стали немного сложнее; данных за большие периоды накапливалось все больше (особенно для подсчета последних 365 дней); подсчеты «уников» за большие периоды так начали нагружать IO, что начали проседать параллельные процессы загрузки данных и подсчеты маленьких периодов. • Поэтому мы решили, что MS SQL secondary (mirror), который доступен в режиме read only, должен заняться полезным делом: • Сделали так, чтобы сервис забирал результаты не с primary, а с secondary сервера. • В результате: • нагрузка на IO систему сильно снизилась.
  • 18. Big Fail • И всё равно надо было предпринимать шаги по масштабированию, так как мы понимали, что долго так не протянем.
  • 19. О масштабируемости • Масштабируется MS SQL AlwaysOn HA group легко: • можно добавить в кластер secondary сервера для подсчетов. • Но это дорого стоит. • Мы начали думать: можем ли мы посчитать «уники» за большие периоды эффективней, чем MS SQL? • Тогда мы бы могли в MS SQL оставить только то, что хорошо и быстро работает: • • • хранилище для исходных данных; хранилище для результатов; подсчеты «уников» за маленькие периоды – до часа.
  • 20. Эффективный алгоритм • Мы придумали быстрый алгоритм, как при помощи Merge Sorta файлов посчитать «уники», нагружая IO и CPU по максимуму, при этом делая минимум лишних операций и используя минимум памяти. • Далее рассмотрим частный случай, когда мы из семи дневных результатов высчитываем недельные «уники».
  • 21. Выгрузка данных в файлы • Из базы данных в память выкачиваем данные за последний закрытый период (например, день), отсортированные по (groupid, userid). • Записываем эти данные в 100 файлов, распределяя по groupid mod 100, чтобы все записи одной группы попали только в один файл. Это необходимо для распараллеливания. • Формат файлов – бинарный, чтобы мы могли четко знать. где именно начинается и заканчивать одна запись. • Мы пробовали использовать json и csv форматы но сразу от них отказались, потому что на парсинг этих файлов уходила львиная доля мощностей CPU. • Исходные данные в таком формате: • • • За один день – 3 Gb За 7 дней – 21 Gb За 365 дней – 1.1 Tb
  • 22. день #1 день #2 день #3 день #4 день #5 день #6 день #7 каждый файл отдельно уже отсортирован по ID_Group, ID_User (1x вначале) сортируем список открытых файлов по ID_Group, ID_User первой считанной записи (дальше в цикле) отдаем дальше запись с наименьшим ID_Group, ID_User берем следующую запись из того файла, чья запись «ушла» перемещаем файл в списке файлов на место, соответствующее следующей считанной записи Отсортированный список всех данных по ID_Group, ID_User Накопленные данные за предыдущую группу можно считать готовыми, когда начинаются данные про следующую группу ID_Group ID_User ActionType G1 U1 7 G1 U1 7 G1 U2 5 G2 U2 G2 U3 данные про поведение конкретного пользователя в рамках конкретной групы
  • 23. Распараллеливаем • Данный алгоритм работает только в одном потоке, то есть, на одном ядре. • Поэтому мы и создавали не 7 файлов, а 100 комплектов по 7 файлов, распределяя по groupid mod 100. • И запустили подсчеты в столько потоков, сколько было ядер на сервере – 24. • Каждый поток обрабатывал отдельный комплект файлов. • После завершения подсчетов все результаты записываем (bulk insert) в MS SQL для передачи далее в «прод». • А выгруженные файлы не удаляем, а оставляем для подсчетов следующих периодов, но не дольше 365 дней. • «Уники» за 7 дней высчитываем за 3 минуты.
  • 25. Нагрузка на CPU • CPU не нагружен на 100% потому, что есть дисковая очередь.
  • 26. Ускоряем ещё больше • Днем, когда сервер отдыхает, можем высчитывать агрегат за 364 дня. Потом после полуночи надо будет сделать Merge Sort всего двум файлам. Ускорим в 5 раз. • Для подсчетов «уников» за последние 364 дня можно использовать комбинацию дневных и месячных агрегатов. Ускорим на 25%. • Для подсчетов можем использовать оба .NET сервера (первый сначала подсчитывает чётные группы, второй – нечётные). Ускорим в два раза.
  • 27. Tips and Tricks • Для подсчета «уников» за 365 дней нам надо открыть много файлов – 365x24 (число ядер). Необходимо под каждый FileHandle выделять такой размер буфера, чтобы он не превышал некую MagicConstant (~1Gb). Иначе Windows Server начинает делать swap памяти. • Файлы, в которых храним числовую (IDs) информацию в бинарном виде, не стоит пытаться зиповать. • Если шедулируете подсчеты, используя Windows Task Scheduler, то по умолчанию у тасков стоит низкий приоритет на ресурсы. Через UI его повысить нельзя – надо экспортировать XML дефиницию таска, повысить в нем соответствующую настройку и импортировать обратно.
  • 28. Итоги • Мы вынесли подсчеты из MS SQL и используем его только как хранилище. К тому же используем не оптимально, так как нам надо, чтобы данные можно было бы хранить с кластеризацией по (groupid, userid). • То есть использование MS SQL не обосновано. Вместо него мы будем использовать или Open Source базы, или переделаем всё на обработку файлов в .NET. • .NET и Windows Server 2008 R2 показал себя как хорошая платформа для обработки данных и файлов • • • быстрая и стабильная с хорошим файл-кешем удобный язык программирования для аппликации параллельной обработки информации.
  • 29. Итоги • «Уники» за 365 дней мы можем посчитать за 4 часа на одном сервере, а потенциально можем посчитать менее чем за час. • Это в десятки раз быстрее, чем может MS SQL. • Подсчеты за меньшие периоды занимают несущественное время. • Количество серверов, необходимых для подсчетов – 2 (+2 для HA). • Количество трудозатрат – 3 человеко-месяца. • А если делать сразу всё правильно – 1 человеко-месяц.
  • 30. Спасибо за внимание! Александр Шарак Руководитель отдела статистики Одноклассники aleksandr.sharak@odnoklassniki.ru