Нагруженный поиск на Sphinx
Sphinx User Conference 2011, St. Petersburg
Роман Павлушко[email protected]
Михаил Тюрин[email protected]
о проекте
• 60М запросов в сутки (AVITO, TORG, API)
• 80К запросов в минуту
• 75К пользователей online
• 50М объявлений всего
• 4М активных объявлений
• 150К новых объявлений в сутки
• 10 новых объявлений в секунду в пики
Sphinx User Conference 2011, St. Petersburg
Sphinx User Conference 2011, St. Petersburg
распределение просмотров на сайте
88% запросов связаны
с поиском!
req/
day,
M
Sphinx User Conference 2011, St. Petersburg
динамика роста
постоянный рост
Sphinx User Conference 2011, St. Petersburg
используемые технологии
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
● автодополнение (suggest)
● поиск по полной базе объявлений
● внутренняя статистика
● поиск по объявлениям (сайт, api)
● поиск похожих объявлений
Sphinx User Conference 2011, St. Petersburg
powered by sphinx
Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям
1
2
3
4
5
Sphinx User Conference 2011, St. Petersburg
похожие объявления
каскад
• 80М запросов в сутки
• 1700 запросов в секунду в пики
• 4М документов в индексе
• размер индексов 2GB
• 46 индексов (основной + категории)
• каждые 10 минут полная переиндексация
• 8 серверов (x16 core)
• 69% запросов без query (43 vs 22 ms)
Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / цифры
Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / скорость
Query Time
Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / offset
Page
первые 50 страниц 99%
M S1 S2 S3 S4 S5 S6 S7
DBmaster 1repca
deploy
londisteindexer
clients
sphinxql
Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / архитектура
• API SphinxQL
• lazy initialization
• по возможности используем multi-query
• вычисляем оптимальный max_matches
• кешируем поисковую выдачу на 1 минуту
• кешируем похожие объявления до ближайшей
переиндексации
• берем из sphinx только ID документов
Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / клиенты
• отдельные конфиги для индексатора и поиска
• workers = prefork threads (проблемы с HUP!)
• отказ от MVA, на каждый фильтр свой атрибут
• на каждую категорию свой индекс
• дисковые индексы без дельты* хранятся в RAM
• отказ от query_log
• настройки под характеристики железа
(max_children, read_buffer, read_unhinted, etc)
Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / настройки sphinx
• tmax < 30 минут
• время на применение услуг к объявлению
• время на премодерацию
• время на переиндексацию
• сохранить быстрые настройки поиска
• поддержать целостность данных
• решить проблему селективности выборки из БД
Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / требования
Sphinx User Conference 2011, St. Petersburg
индексация
пост
роен
ие
снап
шот
а –
18 с
мно
гопо
точн
ая
инде
ксац
ия
item
s_fu
ll –
515
сite
ms_
cat*
– 3
80 c
депл
ой и
ндек
сов
на с
лейв
ы –
120
с
депл
ой м
асте
раи
рота
ция
– 35
с
время переиндексации 11:40
• одна большая база, одна большая таблица ― всё
очень страшно
• но!― всё работает: OLTP, index scan (1K+ / sec)
• 1K+ req / sec, выдача до 50 Mbit / sec
• упирались в кеш / диcк
Sphinx User Conference 2011, St. Petersburg
индексация / хранение объявлений
• MV -- materialized view, "хитрые" триггеры
• repca и londiste с небольшим патчем
• конфиги pg: master ― размазывем io, repca ―
"in-memory pg", version: 9.1.1
• pgbouncer 'ы : разные пулы под разные задачи(сайт, индексация, мониторинг, сервисы)
индексация / хранение объявлений
Sphinx User Conference 2011, St. Petersburg
Sphinx User Conference 2011, St. Petersburg
индексация / репликация дла снапшота
1.1) mv триггеры ( 9.0 )
create constraint trigger имя_триггераafter список_событий on таблица_связанная_с_mv
deferrable initially deferredfor 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
индексация
• сфинксы вызывают базу + psql
• транзакция построения ss
• а в ней функция построения ss
• таблицы и hstore, оверхед hstore: 14 sec / 10M
• параллельное вычитывание ss
• ! seq scan из shared buffers
* ss - снапшот / snapshot
Sphinx User Conference 2011, St. Petersburg
индексация / построение снапшота
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 xwhere x.category_id = 15
Sphinx User Conference 2011, St. Petersburg
индексация
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
fromitems ix ....
where( ix.active ) and ( .... )
Sphinx User Conference 2011, St. Petersburg
индексация
Sphinx User Conference 2011, St. Petersburg
индексация / база в памяти
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 %
pg_buffercache b inner join pg_class c on ( b.relfilenode = pg_relation_filenode(c.oid) )
Sphinx User Conference 2011, St. Petersburg
индексация / фрагментация
select * from pgstattuple(...) repca.items_mv sphinx.x_a_v_i1 repca.items_mv_pkey
table_len 2473418752 2309922816 282746880
tuple_count 4228442 4226761 4249388
tuple_len 2246676901 2243321710 67990208
tuple_percent 90.83 97.12 24.05
dead_tuple_count 5639 0 8819
dead_tuple_len 3135978 0 141104
dead_tuple_percent 0.13 0 0.05
free_space 178386236 27080140 194390312
free_percent 7.12 1.17 68.75
Sphinx User Conference 2011, St. Petersburg
индексация / время построения и чтения
• psql ... -c 'begin; [строим_снапшот]; end;' (18 с)
• в 9.2 не надо будет строить таблицу в принципе
• можно будет из сессии экспортировать
транзакционный снапшот из mvcc
Sphinx User Conference 2011, St. Petersburg
индексация / время построения и чтения
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
рост БД - НО постоянный хитрейт
Sphinx User Conference 2011, St. Petersburg
io мастера теперь не влияет на индексацию
Sphinx User Conference 2011, St. Petersburg
backoffice
CENSORED
Sphinx User Conference 2011, St. Petersburg
backoffice / архитектура
3
1
3
1
3
3 4
1
3
Node 1 Node 2 Node 3 Node 4
Pool
Group 1
4/4/16
Sphinx User Conference 2011, St. Petersburg
backoffice / цифры
• 50M документов в индексе
• размер индексов 16GB
• 8 серверов
• 16 нод (по 2 на сервер)
• ежеминутная индексация
• раз в час мерж дельты
• нагрузки нет (в среднем 30 запросов в минуту)
Sphinx User Conference 2011, St. Petersburg
backoffice / реализация
• основной индекс + дельта
• MVA для поиска по параметрам категории
• дельта по last_update_txtime с нахлестом
• 3 уровня - ноды/группа/pool
• приложение для управления конфигурацией
• медленная полная переиндексация
Sphinx User Conference 2011, St. Petersburg
backoffice / время индексации
Sphinx User Conference 2011, St. Petersburg
автодополнение (suggest)
Sphinx User Conference 2011, St. Petersburg
автодополнение
• обновляем индекс раз в неделю
• 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
автодополнение / цифры
• размер индекса - 25MВ :)
• 200K документов в индексе
• 1M запросов в сутки (кеш работает)
• среднее время выполнения запроса - 0.0003 s!
Почему suggest сделан на sphinx?
Потому что разработка бекенда заняла день,
и это прекрасно работает
Sphinx User Conference 2011, St. Petersburg
cпасибо! вопросы?
Роман Павлушко[email protected]
@pavlushko
Михаил Тюрин[email protected]
Top Related