RTB и его проблематика должны быть знакомы участникам конференции - мало кто сегодня не слышал об этом способе получить много krps с жесткими ограничениями на время генерации ответа.
Вот и компания Qmobi решила поучаствовать в этой гонке и отхватить свой кусок пирога под названием “рынок мобильной рекламы”.
При первом подходе к снаряду задача выглядит довольно простой: вот запрос с критериями, вот база данных с ответами - выбирай по индексу и отвечай.
На самом деле все несколько сложнее. Начать с того, что некоторые критерии отбора - негативные. Затем мы имеем дело с выборкой по десятку индексов, каждый из которых обладает низкой cardinality. И, наконец, мы имеем дело с большими объемами: около 10М строк в исходных данных, около 10К строк в финальной выборке. Ах, нет, еще финальная выборка должна быть отсортирована по приоритету! И надо не забыть про атомарные блокировку и списание средств...
От идеи прототипа на perl пришлось отказаться еще на этапе постановки задачи :)
Итак, мы имеем задачу с интенсивным IO, высокой нагрузкой, высокими скоростями, сложными структурами данных и эвристическими алгоритмами.
Анализ имеющихся вариантов показал, что Go должен прекрасно подойти для этой задачи. О том, на основании каких соображений мы сделали такой вывод, и какие из этих соображений прошли проверку практикой, а какие - нет, будет рассказано в докладе.
Также в докладе будет рассказано о том, как сортировка была заменена случайной выборкой, и чем пришлось заплатить за то, чтобы эта замена оказалась равноценной.
Будет показано, почему мы наплевательски отнеслись к гипотетической потере 20% возможностей поучаствовать в аукционе, и почему реальный процент потерь много ниже.
Будет раскрыта роль СУБД MySQL в этом проекте, со всем блеском высокой производительности и нищетой отказоустойчивости.
Вопросы геотаргетинга, использования PostGIS и кэширования результатов поиска региона по координатам будут затронуты вскользь, как неоднократно обсуждавшиеся на этой и подобных конференциях.
А вот анатомия производительности приложения на Go будет рассмотрена подробнейшим образом - с графиками и числами.
Также подробно будут рассмотрены наши победы и поражения в борьбе со статис
2. Немного о Qmobi.com
• Компания Qmobi занимается
• интернет-рекламой
• продвижением мобильных приложений
• без RTB DSP просто не может
• Стек технологий (.Net), до настоящего
времени использовавшийся в компании, не
подходит под задачу
• и это прекрасно - мы свободны в
выборе!
3. Немного о выборе
•на самом деле - выбор совсем не широк
•.Net
•JVM-экосистема
•все_остальное
•нет, это нельзя писать на perl
•да, мы проверяли
•из всего_остального мы выбрали Go
•да, это произвол
4. Немного о докладе
•никаких цифр и графиков
•розовые единороги и радуга повсюду
•основная мысль - выбор стал шире:
•Net
•JVM-экосистема
•Go
•все_остальное
7. Как все начало заканчиваться
• 4 часа сборки
• C++
• Описание интерфейсов в терминах
наследования
• Запутанная архитектура
• JSON-конфиги, xml-конфиги
• Zookeeper
• ZeroMQ
• Redis
11. Немного о задаче
•1000 пользователей
•по 100 кампаний
•по 100 креативов на
кампанию
•итого - 10 000 000 строк
12. Немного о задаче
•1000 пользователей
•по 100 кампаний
•по 100 креативов на кампанию
•итого - 10 000 000 строк
•10krps
•можно и больше, но не нужно
•мы ограничены бюджетом
13. Еще о задаче
• Задача выглядит прямой как палка
и простой как 3 копейки
• вот креативы
• вот запросы
• матч один к другому, и все получится
• задача выглядит хорошо масштабирующейся
• база креативов обновляется редко
• базе креативов не нужна strong consistency
14. А теперь - о проблемах
• banker - не масштабируется
• чтобы масштабировать banker нам
нужна CA (в терминах CAP-теоремы)
СУБД
15. А теперь - о проблемах
• banker - не масштабируется
• чтобы масштабировать banker нам
нужна CA (в терминах CAP-теоремы)
СУБД
• bidder - это расчет пересечения
множеств
• а пересечения множеств - это или
сортировка, или полный перебор
16. А теперь - о проблемах
• banker - не масштабируется
• чтобы масштабировать banker нам нужна CA (в
терминах CAP-теоремы) СУБД
• bidder - это расчет пересечения множеств
• а пересечения множеств - это или сортировка, или
полный перебор
• а еще bidder - это сортировка выборки
• по приоритету
• по времени последнего показа
• по цене показа
• по остатку на счете кампании
19. Об очевидных
технических решениях
• тривиальный код сетевого взаимодействия
на Go
• из нестандартного OpenRTB протокол
и СУБД драйвер
• nginx - знамя русского хайлоада - на входе
• просто для обработки таймаута
20. Об очевидных
технических решениях
• тривиальный код сетевого взаимодействия
на Go
• из нестандартного OpenRTB протокол
и СУБД драйвер
• nginx - знамя русского хайлоада - на входе
• просто для обработки таймаута
• кеширование креативов и кампаний в памяти
• раз уж они влезают
21. Об очевидных
технических решениях
• Geo-таргетинг делается по кодам ISO-3166
• коды получаются из координат с помощью
PostGIS
• Полная база работает недопустимо медленно,
пришлось создать свою выборку, только с
границами интересующих нас областей
• примерно треть запросов не содержит координат
• практически ни один запрос не содержит кодов
ISO-3166 - а по стандарту должен!
22. О спорных
технических решениях
• MySQL как banker
• прижился со стадии прототипа
• да, на триггерах
• 10krps - это примерно 20k updates per second
• backup есть, failover и balancing нет
• и backup может существенно отставать
23. О спорных
технических решениях
• Logger на InfluxDB
• InfluxDB - странная база, но она работает
• Она - time series
• В нее же пишем метрики для Grafana
24. О спорных
технических решениях
• Logger на InfluxDB
• InfluxDB - странная база, но она работает
• Она - time series
• В нее же пишем метрики для Grafana
• Обычно для логов используется Elastic Search
• Но он слишком сильно грузит диски
• И даже известно, почему
25. О самому-страшно
технических решениях
• Как устроена выборка по таргетингу
• НИКАК!
• мы берем случайную запись, и проверяем
ее на соответствие
• если не подошла - берем еще одну
случайную
• и так, пока не выйдет время (100ms)
26. О самому-страшно
технических решениях
• Как устроена выборка по таргетингу
• НИКАК!
• мы берем случайную запись, и проверяем ее
на соответствие
• если не подошла - берем еще одну случайную
• и так, пока не выйдет время (100ms)
• И это работает
• и мы можем это доказать
27. О самому-страшно
технических решениях
• На самом деле - это не совсем правда
• самый нужный таргетинг захардкожен в
структуру кеша
• случайная выборка происходит не по
всему пространству, а по подмножеству,
ограниченному
Device + OS + version + Geo
28. О самому-страшно
технических решениях
• Подлый удар от Go sheduler
• переключение go-routines происходит по
IO
• это значит - пока мы ползаем по базе, мы
не даем другим рутинам работать
• пришлось вставить
runtime.Gosched() в цикл
31. Что дальше
• заменить MySQL на CA кластер.
• Возможно, придется написать свой
• таргетинг по произвольному набору
параметров - второй подход к снаряду
• анализатор логов - выяснить, что нужно
бизнесу от него, и написать
соответствующий интерфейс
• автоматическая обратная связь - именно
для нее все и затевается
33. Итоги
• довольно быстрый результат
• 3 человеко-месяца
• высокоэффективный код
• 1 сервер тянет 10krps
• уперлись мы в MySQL
• MySQL уперся в CPU
34. Итоги
• довольно быстрый результат
• 3 человеко-месяца
• высокоэффективный код
• 1 сервер тянет 10krps
• уперлись мы в MySQL
• MySQL уперся в CPU
• полностью свой проект
• не считая MySQL и nginx