RT индексы в поиске Avito
Вячеслав Крюков, Avito
Поиск в Avito
● Активные объявления
● Контекстные объявления
● BackOffice
● В докладе про поиск активных объявлений на RT (Real Time) индексах
Поиск «до» внедрения RT индексов
Поиск «до» внедрения RT индексов
● Активное объявление
появилось в Master базе
Поиск «до» внедрения RT индексов
● Через логическую
репликацию оно стало
доступно на сервере, где
происходит индексация
Поиск «до» внедрения RT индексов
● Каждые 5-8 мин строятся Plain
индексы и с этой задержкой наше
объявление проиндексировано
● В это время репликация на паузе
Поиск «до» внедрения RT индексов
● Plain индексы раздаются по
udp на поисковые сервера,
битые индексы дораздаются
через rsync
Поиск «до» внедрения RT индексов
● Ротация Plain индексов
делает доступным в поиске
наше объявление
Поиск «до» внедрения RT индексов
● Пользователь делает
поисковый запрос на сайте
или в мобильном приложении
через интернет
Поиск «до» внедрения RT индексов
● Его принимает однин из
бэкендов
Поиск «до» внедрения RT индексов
● HAProxy бэкенда отправляет
SphinxQL запрос на демон
Searchd и он выполняется на
индексе одной из категории
Поиск «до» внедрения RT индексов
● Или выполняется
распределенный запрос по
индексам всех категорий
Ожидания от внедрения RT индексов
● Мгновенная доступность нового объявления в поиске
● Надежность
● Масштабируемсть
● Обслуживать высокую поисковую нагрузку (17000 RPS в пике)
● Сотни изменений в секунду
● Комбинированное решение, с тем что было «до»
● Унификация настроек
Чем отличается поиск на RT индексах от Plain?
● Indexer и Main+Delta схема внутри демона Searchd
● Indexer не нужен
● Запросы на изменения данных идут к Searchd
● Ram + Disk чанки
● Внутренние Kill листы
Изменения данных в RT индексах
● INSERT/REPLACE
● UPDATE
● DELETE
Поиск «после» внедрения RT индексов
Поиск «после» внедрения RT индексов
● Активное объявление
появилось в Master базе
Поиск «после» внедрения RT индексов
● Через логическую
репликацию оно стало
доступно на сервере, где
происходит индексация
Поиск «после» внедрения RT индексов
● По факту новых данных в
реплике генерируется
событие с Id объявления в
очереди PGQrt
Поиск «после» внедрения RT индексов
● Событие считывается
консьюмером RT Indexer
Поиск «после» внедрения RT индексов
● Если у RT Indexer
установлен флаг active, то
он делает SELECT из
реплики данных по Id
объявления в событии
Поиск «после» внедрения RT индексов
● Если данные найдены, то
RT Indexer выполнит запрос
REPLACE к демону Searchd
● Cоответствующие
изменения отображается в
RT индексах
Поиск «после» внедрения RT индексов
● Если данные не найдены,
то делается запрос DELETE
Поиск «после» внедрения RT индексов
● RT Indexer отмечает событие
в очереди обработанным
● Если при поступлении
события флага active не
было, то эта отметка
делается сразу и никакой
др. работы не делается
Отставание «До» и «после» выкатки RT индексов
Количество объявлений в общем индексе (Distr
Index)
Количество изменяемых объявлений во времени
Поиск «после» внедрения RT индексов
● Зачем две очереди PGQm и
PGQrt?
Зачем две очереди PGQm и PGQrt?
● Очередь PGQm нужна для Londiste репликации
● Очередь PGQrt влючена последовательно
● Данные есть в реплике - операция REPLACE
● Данных нет в реплике - операция DELETE
● Гонки данных не возможны
● Возможен оверхед по уже выполненной операции
Поиск «после» внедрения RT индексов
● Зачем нужны Plain
индексы?
Зачем нужны Plain индексы?
● Нельзя бесконечно накапливать изменения в RT индексах
● Нужно сбрасывать сотояние RT индексов — делать rebuild
● Plain индексы играют промежуточную роль
● Можем откатиться к решению «до», если RT поломается
Поиск «после» внедрения RT индексов
● Rebuild RT индексов
● Репликация на паузе
● Переиндексация Plain
индексов
Поиск «после» внедрения RT индексов
● Rebuild RT индексов
● Репликация на паузе
● Раздача Plain индексов
Поиск «после» внедрения RT индексов
● Rebuild RT индексов
● Репликация на паузе
● Принудительная пауза, для
холостой прокрутки PGQrt
Поиск «после» внедрения RT индексов
● Rebuild RT индексов
● Репликация на паузе
● RELOAD Plain индексов
Поиск «после» внедрения RT индексов
● Rebuild RT индексов
● Репликация на паузе
● ATTACH WITH TRUNCATE
Plain индексов в RT
Поиск «после» внедрения RT индексов
● Rebuild RT индексов
закончен
● Репликация снята с паузы
● Установлен флаг active
● RT indexer обрабатывает
очередь PGQrt
Rebuild RT индексов
Изменение размера Ram чанка
Поиск «после» внедрения RT индексов
● Поисковые запросы через
бэкененды и HAProxy
поступают на демон
Searchd и он их
отрабатывает на RT
индексах
Поисковая нагрузка
Поиск «после» внедрения RT индексов
● Зачем нужен Failover ?
Поиск «после» внедрения RT индексов
● Следит за отставанием
очереди PGQrt
Поиск «после» внедрения RT индексов
● Следит за отставанием и
кол-ом объявлений в RT
индексах
Поиск «после» внедрения RT индексов
● Следит за окончанием
периода активности RT
indexer
● Следит за перезапуском
или отсутствием процесса
RTIndexer
Поиск «после» внедрения RT индексов
● И устанавливает флаг
rebuild если есть
нарушения
● После этого начинается
Rebuild RT индексов
Что еще делает Failover?
● Перезапуск RTIndexer при зависании
● Нотификация в Slack
Неконтролируемое отставание очереди PGQrt
Контролируемое отставание очереди PGQrt
RT Indexer
● Python демон с подключенной библиотекой на Go
RT Indexer
● Если не установлен флаг active, RT Indexer прогоняет
очередь PGQrt вхолостую, без какой-либо работы
RT Indexer
● В RT Indexer можно выделить три основные сущности оформленные в
виде Go рутин и соединенные последовательно через каналы в
Pipeline
RT Indexer
● Сортирует Id объявлений в пачки по категориям, возвращает канал,
для передачи таких пачек
RT Indexer
● Передает отсортированные пачки Id в этот канал по мере
поступления событий из PGQrt
RT Indexer
● Слушает канал с отсортированными по категориям пачками Id
объявлений
● Извлекает для них данные объявлений из реплики исползуя конфиг
для Plain индексов
RT Indexer
● Создает два канала с данными объявлений по категориям для запросов
REPLACE и id удаляемых объявлений для запросов DELETE
● Если данные для Id объявления не найдены, то оно считается удаляемым
RT Indexer
● Передает в эти каналы данные по мере поступления пачек Id
объявлений
RT Indexer
● Слушает канал с данными объявлений по категориям для запросов
REPLACE
● Слушает канал с Id объявлений для удаления
● Формирует и выполняет запросы REPLACE и DELETE
RT Indexer
● Выполняются запросы REPLACE
и DELETE для категории 1
RT Indexer
● Выполняются запросы REPLACE
и DELETE для категории 2
RT Indexer
● Выполняются запросы REPLACE
и DELETE для категории Nc
RT Indexer
● В RT Indexer обрабатываются абсолютно все ошибки, падения не
допускаются
RT Indexer
● В RT Indexer отмечаются обработанными абсолютно все события
RT Indexer
● Ошибки пишутся в общий для всех канал ошибок
● Канал ошибок слушает специальная Go рутина
RT Indexer
● Если встречается критичная ошибка, то выставляется состояние
rebuild
● Аварийного завершения не происходит
Критичные ошибки в RT Indexer
● Возникновение ошибок выполнения запросов
● Появление нового поискового сервера
● Ошибки конфигурации
Настройка производительности
● Медленные запросы REPLACE/DELETE — отставание очереди PGQrt
● rt_mem_limit срабатывает поиндексно
● Необходим некоторый избыток rt_mem_limit
0.95 время выполнения SELECT
Максимальное время выполнение REPLACE
Отставание
Полное спокойствие в пик трафика
Что реально получили «после» внедрения RT индексов
● Попадание нового объявление в поиск с 10 сек отставанием
● Как и прежде держит высокую нагрузку
● Не вычитываем повторно данные
● Уменьшили трафик в сети
● Гармонично вписали решение c RT индексами в ранее существующую
систему
● Получили надежную систему
Спасибо, вопросы?

Sphinx 3.0 и RT-индексы на основном поиске Avito / Андрей Смирнов, Вячеслав Крюков (Avito)