Lucene - это популярный движок для построения полнотекстовых поисков. Им пользуются Twitter, LinkedIn, Apple и ряд других немаленьких компаний. В 2009 году Одноклассники запустили первый поиск на Lucene, и за два года к поиску пользователей добавились еще 5 других поисковых сервисов. В докладе будет рассказано о том, как устроены эти поисковые сервисы.
Так же в докладе расскажем о системе, которая одновременно ищет во всех индексах, а так же использует информацию о пользователе чтобы улучшить релевантность выдачи. Система обрабатывает более 60 млн запросов в день, и на каждый ответ тратит в среднем 90мс.
Видео на ютубе в 3 частях:
1 - http://youtu.be/htt2FIQolOs , 2 - http://youtu.be/qhj4Voy0nYU , 3 - http://youtu.be/FFk_6CprDNc
2. Одноклассники в цифрах
• Что у нас есть:
– 100 млн пользователей;
– 3.3 млн групп;
– .....
• 4.1 млн пользователей онлайн;
• В секунду:
– 250. тыс. страниц, 50мс, 70Гбит/с;
– 6 тыс. сообщений и комментариев;
– 1.5 тыс. поисковых запросов.
1
3. Зачем нам понадобились свои поисковые
системы?
• Пользователь не всегда знает, как именно
регистрировался искомый друг
• На сайте были огромные каталоги групп и
сообществ
• Планировались новые сервисы, которым
понадобится поиск
• Как правило, человек ищет то, что уже есть у
кого-то из его друзей
2
4. Почему Lucene?
• Поиск по MS SQL базе был крайне медленным
• На Java написано 99% нашего кода, поэтому
Sphinx даже не смотрели
• Apachе Lucene/Solr поддерживаются большим
сообществом и хорошо себя зарекомендовали
• Уже был опыт использования Solr
• Быстрый поиск других поисковых
Java-проектов результатов не дал
3
5. Как устроен Lucene?
The bright Term DocId DocId Values
blue blue 1,2 1 333, Author A
Index Reader & Searcher & Query parser
butterfly bright 1,2 2 777, Author C
hangs on
Tokenizers & Filters & IndexWriter
butterfly 1
the breeze
breeze 1
hangs 1
Under blue
sky, in bright need 2
sunlight, search 2
one need sky 2
not search
around
Term DocId DocId Values
It’s best to best 1 1 555, Author C
forget the forget 1
great sky
great 1
and to retire
from every retire 1
wind sky 1
wind 1
4
6. Требования к системе индексов
• Отказоустойчивость и масштабируемость
• Высокая производительность поисковых
серверов
• Гибкое индексирование
• Возможность сбора дополнительной
информации перед индексацией
• Возможность анализа готового индекса
5
7. Что нас не устроило в Solr
• Solr:
– сервер использует только один процессор
– репликация индексов на bash-скриптах
– http - это дорого и медленно
– сложно модифицировать
• Но Lucene нас устраивает, поэтому пишем
свой сервер
6
8. Архитектура
Presentation
Query
Event
Result
Result
Search processing system Read Services
Update/Notify
Query
Read
Results
Index Replication Indexer + DB
7
9. Требования к поисковой системе
• Отказоустойчивость
• Использование социального графа
• Эффективность
• Простое изменение и расширение
функциональности
• Сбор статистики по пользователям
• Высокая пропускная способность
8
10. Как работает поисковая система
Get session for Schema
Schedule queries
Execute queries
waitAll ()
waitFor (queries complete)
waitAtLeast (result items)
Reduce results
Load results
9
11. Проблемы: работа с индексом
• Lucene активно читает файлы во время поиска
• Пробовали:
– Диск с FSDirectory и NIODirectory
– RamDrive с FSDirectory и NIODirectory
– Lucene RamDirectory
– Собственный UnsafeDirectory
• Победил:
– HeapDirectоry файлы как byte[] в хипе
10
12. Проблемы: ThreadLocal кэши
• Долгий GC из-за уймы мелких объектов в хипе
• Причины:
– Lucene использует ThreadLocal кэши для
некоторых объектов
– Jboss Remoting на каждое соединение содает
поток, а их тысячи
• Первое решение:
– Пул для выполнения запросов
• Второе решение:
– Делая другую оптимизацию, убрали эти кэши
11
13. Проблемы: медленные хранимые поля
• Медленная работа с хранимыми полями
• Причина:
– При считывании хранимого поля создается много
мусора и производятся ненужные операции
• Решение:
– Считывать значение в нужный тип сразу из byte[]
• Результат:
– На порядок быстрее стали операции с хранимыми
полями
– Время GC упало в 2 раза
12
14. Распознавание полей
• Поиск пользователей идет по следующим полям:
имя и фамилия, город, страна, интервал возростов
• Друга можно искать, вводя известные данные:
«илья широков 30»
«илья широков москва»
«илья широков 25-30 россия»
Query Line
User Term Term Search
Index Collector Dict. System
Fields Query
13
15. Поиск по возрасту
• Стандартные решения:
– Добавление всех подходящих терминов
– Префиксные термины для снижения количества
терминов в запросе
– Запрос к FieldCache
– Фильтр результатов
• Наше решение:
– Возраст хранится ввиде даты: yyyymmdd
– Запрос по текстовым полям оборачивается в
фильтрующий запрос, который проверяет отбраные
документы по хранимому полю
14
16. Поиск музыки
• В базе есть:
– артисты; альбомы; композиции
– не сортированые музыкальные композиции
• Три точности совпадения:
точное; все слова из запроса; некоторые слова из запроса
• Поиск всегда идет по всем видам документов
• От точности совпадения зависит поведение UI
• На место в выдаче влияет рейтинг документа
• С индекса собираются всевозможные топы
15
17. Индексация музыки
• Все храним в одном индексе
• У каждого документа:
– в id зашит его тип (артист; альбом; композиция; файл)
– тип как отдельное поле
– рейтинг как параметр индексации
– рейтинг как хранимое поле
• Текстовые поля:
– по отдельности
– необходимые комбинации
– 2 представления текста: оригинал + фонетика
16
18. Поиск музыки
• Пробовали:
– Отдельный запросы для каждого типа
– Повторные запросы с меньшей точностью
– Настройка оценщика веса для результата
• Решение:
– Запрос состоит из комбинаций: точность + поле данных
– Для каждой комбинации есть интервал значений весов
– Вес из подзапроса нормализуется в интервал
комбинации
– Если документ отвечает запросу, сразу вычисляем его
тип и добавляем в соответствующий коллектор
17
Хотелось находить, несмотря на опечатки, с учетом истории, и ранжировать не по айдишке
НедавноSQLперестал искать по именам даже в админке
Инвертированый индекс - это индексная структура, которая хранит не отдельные поля документов, а данные из этих полей: слова, цифры и т.д. Через такую структуру можно быстро находить документы, содержащие необходимые слова, все или часть из них.
Эти требования были выработаны на основании нашего опыта и моделирования необходимого функционала
Такая схема обеспечивает лучшую стабильностьи возможности оптимизации, но нет возможности сделать NRTГлавным конкурентом такой схемы является препроцессор, которые готовит данный и рассылает их на ПС. Появляется рассинхронизация, двойная работа на ПС, негде анализировать индексы.Реплицируем необходимые фаилы ввиде byte[]
Мы знаем о пользователях гораздо больше, чем обычная поисковая система, и мы стараемся этим пользоваться. Эффективность – из-за отсутствия схем всегда собирается полный граф, может быть меньше вызовов на подготовке результатовПроблемы первой версии с бобром и лосёмЭто требования для системы которой одновременно пользуется более 70.000 человек.
Схема описывает, какие данные из соц графа (более 30 видов) нужны для запросаСейчас 5 схем и 4 вида результатов, будет большеИндексы не храняться т.к. Проще пересобирать их при необходимости нежели пытаться апдейтить 100.000.000 индивидуальных индексовКэширование результатов было, но отказались – проще когда надо повторить запрос. Такой же опыт у твиттераМгновенный поиск запускали одновременно с гуглом
ВLinux очень эффективное кэширование, но тут оно не сработалоВыделеные сервера для выполнения запросов позволили выжать максимум из них
Данные проблемы следствие универсальности Lucene, но нам нужна эффективностьПотребовалось переписать несколько ключевых классовСнизило время GCв 2 раза для обычных поисков и в разы ускорило поиск музыки, схоже с тем что будет в 4ой Lucene
Поиск должен быть не только быстрым но и удобнымБыли моменты когда бал только детальный и только строка – оба варианта вызывали недовольствоСборка словаря встроена как конфигурируемая фича и делается автоматическиТак же через отдельный словарик сделаный с SQL данных находим странуНераспознанные слова считаются именамиПроблемы с «Иван Ростов»Сделать как то иначе мешает черезчур большой размер словаряВ словарь попадают только слова с определенной частотой
RangeQuery даже не пробовалиFieldCacheработающий в LinkedIn не подошел из-за того что у нас боьшие партицииМеханизм фильтрации Lucene тоже не работает для таких больших индексов
Как Luceneотбирает документы:Документ должен отвечать булевой логике запросаТочность соответствия вычисляется с использованием Векторной модели (vector space model) – получается вес результата
Для каждого подзапроса есть база, размер интервала и ожидаемое максимальное значение.Музыка работает так медленно т.к. требования сильно изменились к моменту запуска. При новых требованиях хранение 4 видов документов в одном индексе создает большие проблемы.
Микропоиски:ДрузейИгры и приложенияПодарочкиПомощьГородаCPU 15-30%С поиска сообществ случайно сняли более 3000 в секунду без нагрузки на серверЧто дал переход на Lucene для поиска пользователей:Вместо установки еще минимум 16 серверов с дорогущим MS SQL мы поставили 13 серверов с Linux и Java (могли обойтись 8ю)Время поиска упало до десятков милисекундПолучили обработку опечаток, выдачу с учетом точности совпадения, поиск по девечий фамилии и старым именам и городамЗатраты : 5 месяцев одного программиста, без знания как устроен портал и поисковые системыМикропоиски работают на своем движке, но скорее всего скоро смигряем на Lucene