1. Нагруженный поиск на Sphinx
Роман Павлушко Михаил Тюрин
rpavlushko@avito.ru mtyurin@avito.ru
Sphinx User Conference 2011, St. Petersburg
2. о проекте
• 60М запросов в сутки (AVITO, TORG, API)
• 80К запросов в минуту
• 75К пользователей online
• 50М объявлений всего
• 4М активных объявлений
• 150К новых объявлений в сутки
• 10 новых объявлений в секунду в пики
Sphinx User Conference 2011, St. Petersburg
3. распределение просмотров на сайте
88%
запросов
связаны
с поиском!
Sphinx User Conference 2011, St. Petersburg
4. динамика роста
постоянный рост
req/day, M
Sphinx User Conference 2011, St. Petersburg
5. используемые технологии
Web-server nginx
Application php-fpm + eaccelerator
DB postgresql + pgbouncer + londiste
NoSQL redis
Search Engine sphinx
Cache/Session memcached + magent
Monitoring munin, monit, bash
... git, python, etc
Sphinx User Conference 2011, St. Petersburg
6. powered by sphinx
● поиск по объявлениям (сайт, api)
● поиск похожих объявлений
● автодополнение (suggest)
● поиск по полной базе объявлений
● внутренняя статистика
Sphinx User Conference 2011, St. Petersburg
9. поиск по объявлениям / цифры
• 80М запросов в сутки
• 1700 запросов в секунду в пики
• 4М документов в индексе
• размер индексов 2GB
• 46 индексов (основной + категории)
• каждые 10 минут полная переиндексация
• 8 серверов (x16 core)
• 69% запросов без query (43 vs 22 ms)
Sphinx User Conference 2011, St. Petersburg
10. поиск по объявлениям / скорость
Query Time
Sphinx User Conference 2011, St. Petersburg
11. поиск по объявлениям / offset
первые 50 страниц 99%
Page
Sphinx User Conference 2011, St. Petersburg
12. поиск по объявлениям / архитектура
clients
sphinxql
M S1 S2 S3 S4 S5 S6 S7
deploy
DB
indexer repca londiste master 1
Sphinx User Conference 2011, St. Petersburg
13. поиск по объявлениям / клиенты
• API SphinxQL
• lazy initialization
• по возможности используем multi-query
• вычисляем оптимальный max_matches
• кешируем поисковую выдачу на 1 минуту
• кешируем похожие объявления до ближайшей
переиндексации
• берем из sphinx только ID документов
Sphinx User Conference 2011, St. Petersburg
14. поиск по объявлениям / настройки sphinx
• отдельные конфиги для индексатора и поиска
• workers = prefork threads (проблемы с HUP!)
• отказ от MVA, на каждый фильтр свой атрибут
• на каждую категорию свой индекс
• дисковые индексы без дельты* хранятся в RAM
• отказ от query_log
• настройки под характеристики железа
(max_children, read_buffer, read_unhinted, etc)
Sphinx User Conference 2011, St. Petersburg
15. поиск по объявлениям / требования
• tmax < 30 минут
• время на применение услуг к объявлению
• время на премодерацию
• время на переиндексацию
• сохранить быстрые настройки поиска
• поддержать целостность данных
• решить проблему селективности выборки из БД
Sphinx User Conference 2011, St. Petersburg
16. построение
снапшота – 18 с
индексация
многопоточная
индексация
items_full – 515 с
items_cat* – 380 c
Sphinx User Conference 2011, St. Petersburg
время переиндексации 11:40
деплой индексов
на слейвы – 120 с
деплой мастера
и ротация – 35 с
17. индексация / хранение объявлений
• одна большая база, одна большая таблица ― всё
очень страшно
• но! ― всё работает: OLTP, index scan (1K+ / sec)
• 1K+ req / sec, выдача до 50 Mbit / sec
• упирались в кеш / диcк
Sphinx User Conference 2011, St. Petersburg
18. индексация / хранение объявлений
• MV -- materialized view, "хитрые" триггеры
• repca и londiste с небольшим патчем
• конфиги pg: master ― размазывем io, repca ―
"in-memory pg", version: 9.1.1
• pgbouncer 'ы : разные пулы под разные задачи
(сайт, индексация, мониторинг, сервисы)
Sphinx User Conference 2011, St. Petersburg
20. индексация
1.1) mv триггеры ( 9.0 )
create constraint trigger имя_триггера
after список_событий on таблица_связанная_с_mv
deferrable initially deferred
for each row execute procedure repca.mv_refresh_trg();
1.2) mv рефреш функция
CREATE OR REPLACE FUNCTION repca.mv_refresh_trg() RETURNS trigger AS
$$
begin
delete from repca.items_mv mv where ( mv.item_id = OLD.item_id );
insert into repca.items_mv select * from repca.items_v v where ( v.item_id = OLD.item_id );
return null;
end;
$$
LANGUAGE 'plpgsql';
Sphinx User Conference 2011, St. Petersburg
21. индексация / построение снапшота
• сфинксы вызывают базу + psql
• транзакция построения ss
• а в ней функция построения ss
• таблицы и hstore, оверхед hstore: 14 sec / 10M
• параллельное вычитывание ss
• ! seq scan из shared buffers
* ss - снапшот / snapshot
Sphinx User Conference 2011, St. Petersburg
22. индексация
2) построение снапшота
begin;
set transaction isolation level serializable;
select sphinx.x_prepare_active_items({{ idx }});
end;
3) hstore
select
...
(x.tag -> 'val188')::smallint as val188,
(x.tag -> 'val187')::smallint as val187,
(x.tag -> 'val184')::smallint as val184,
...
from sphinx.x_a_v_i1 x
where x.category_id = 15
Sphinx User Conference 2011, St. Petersburg
23. индексация
create view repca.items_v as
select
....
ix.item_id as item_id,
...
sphinx.x_get_pure_params (
case ix.category_id
when 9 then (select hstore(cx.*) from options.category_9 cx where cx.active and (cx.item_id = ix.item_id))
when 10 then (select hstore(cx.*) from options.category_10 cx where cx.active and (cx.item_id = ix.item_id))
when 11 then (select hstore(cx.*) from options.category_11 cx where cx.active and (cx.item_id = ix.item_id))
...
when 109 then (select hstore(cx.*) from options.category_109 cx where cx.active and (cx.item_id = ix.item_id))
end
) as tag_params
from
items ix ....
where
( ix.active ) and ( .... )
Sphinx User Conference 2011, St. Petersburg
24. индексация / база в памяти
pg_buffercache b
inner join pg_class c on ( b.relfilenode = pg_relation_filenode(c.oid) )
rel buffers_mb rel_mb all in
memory
items_mv 2359 2358 100 % seq scan и фильтры,
вычитка через вьюшку-
запрос
x_a_v_i1 2202 2201 100 % снапшот -- ! seq scan Ы
items_mv_pkey 266 266 100 % так как londiste
pg_toast_91311 26 26 100 %
pg_toast_19818921 24 24 100 %
pg_toast_2619 9 9 100 %
pg_toast_91311_index 2 2 100 %
Sphinx User Conference 2011, St. Petersburg
26. индексация / время построения и чтения
• psql ... -c 'begin; [строим_снапшот]; end;' (18 с)
• в 9.2 не надо будет строить таблицу в принципе
• можно будет из сессии экспортировать
транзакционный снапшот из mvcc
Sphinx User Conference 2011, St. Petersburg
27. индексация / время построения и чтения
explain (analyze, buffers)
select * from sphinx.x_a_v_i1;
"Seq Scan on x_a_v_i1 (cost=0.00..293363.20 rows=11283200 width=172)
(actual time=0.014..4880.666 rows=4229686 loops=1)"
" Buffers: shared hit=282080"
"Total runtime: 8996.531 ms"
explain (analyze, buffers)
select * from sphinx.x_a_v_i1 where category_id = 27 -- 27 - "шмотки" -- фильтр-предикат
на категорию
"Seq Scan on x_a_v_i1 (cost=0.00..296876.50 rows=56440 width=172) (actual time=0.044..
3593.978 rows=712912 loops=1)"
" Filter: (category_id = 27)"
" Buffers: shared hit=282202"
"Total runtime: 4308.269 ms"
Sphinx User Conference 2011, St. Petersburg
28. рост БД - НО постоянный хитрейт
Sphinx User Conference 2011, St. Petersburg
29. io мастера теперь не влияет на индексацию
Sphinx User Conference 2011, St. Petersburg
30. backoffice
E D
O R
N S
C E
Sphinx User Conference 2011, St. Petersburg
31. backoffice / архитектура
1
1 4/4/16
1
Pool
3
3
3
Group 1
3
3 4
Node 1 Node 2 Node 3 Node 4
Sphinx User Conference 2011, St. Petersburg
32. backoffice / цифры
• 50M документов в индексе
• размер индексов 16GB
• 8 серверов
• 16 нод (по 2 на сервер)
• ежеминутная индексация
• раз в час мерж дельты
• нагрузки нет (в среднем 30 запросов в минуту)
Sphinx User Conference 2011, St. Petersburg
33. backoffice / реализация
• основной индекс + дельта
• MVA для поиска по параметрам категории
• дельта по last_update_txtime с нахлестом
• 3 уровня - ноды/группа/pool
• приложение для управления конфигурацией
• медленная полная переиндексация
Sphinx User Conference 2011, St. Petersburg
34. backoffice / время индексации
Sphinx User Conference 2011, St. Petersburg
36. автодополнение
• обновляем индекс раз в неделю
• source: парсим access_log в БД
• чистим мусор (not found, stop words)
• вычисляем популярные запросы (order by rank)
• enable_star = 1 ― ищем по маске
• sql_attr_string ― храним фразу в sphinx
• учитываем категорию при поиске
• кеш работает (~1% запросов к sphinx)
Sphinx User Conference 2011, St. Petersburg
37. автодополнение / цифры
• размер индекса - 25MВ :)
• 200K документов в индексе
• 1M запросов в сутки (кеш работает)
• среднее время выполнения запроса - 0.0003 s!
Почему suggest сделан на sphinx?
Потому что разработка бекенда заняла день,
и это прекрасно работает
Sphinx User Conference 2011, St. Petersburg
38. cпасибо!
вопросы?
Роман Павлушко Михаил Тюрин
rpavlushko@avito.ru mtyurin@avito.ru
@pavlushko
Sphinx User Conference 2011, St. Petersburg