Задача Яндекса – найти ответ на вопрос пользователя. Но технологии поиска этого самого ответа бывают разными. Скажем, поиск по интернету и по письмам очень сильно различаются. Поиск по почте – это особенный продукт, уникальный и сложный.
В первую очередь, Яндекс.Почта – это огромный объём данных. У нас хранится около 10 миллиардов писем – это почти столько же, сколько страниц в индексе веб-поиска Яндекса. При этом поисковых запросов примерно в 1000 раз меньше, чем запросов к поиску по интернету.
Зато в поиске по Почте очень важна полнота результатов: если поиск по интернету не найдёт один-единственный сайт из трёх миллионов по запросу «пластиковые стулья», этого никто (кроме, разумеется, вебмастера этого сайта) не заметит. Гораздо критичнее, если потеряется письмо с важным адресом или паролем.
По этим причинам в поиске по Почте существует
Архитектурные особенности
Поступающие в почту письма можно индексировать в хронологическом порядке. В этом случае, как только на первом сервере закончится дисковое пространство, мы начнем строить индекс на втором и так далее. Но такой способ не гарантирует полноту результатов поиска: для полного ответа нужно получить результаты с каждого сервера, а, поскольку время ответа от каждого сервера разное, то из-за сетевых задержек мы можем потерять часть данных.
Чтобы обеспечить полноту результатов, весь поисковый индекс для некоторого пользователя хранится на одном сервере и полностью дублируется на другом – если один сервер недоступен, то мы ищем на дублирующем.
Когда система работает в штатном режиме (все серверы функционируют, все дата-центры доступны), половина поисков отправляется на сервер в одном ДЦ, а вторая половина – на сервер в другом ДЦ. Благодаря этому поисковая производительность увеличивается в два раза.
Технологические особенности
На каждом сервере располагается индекс по письмам пяти миллионов пользователей. Можно строить его разными способами: например, по индексу на пользователя, но в таком случае возникает большая нагрузка на файловую систему, а также требуется огромное количество аппаратных ресурсов и ресурсов операционной системы (потоки и файловые дескрипторы) для поиска.
Другой вариант – все пользователи в одном индексе. Однако этот вариант ненадёжен: если произойдёт сбой, то сразу миллионы пользователей останутся без поиска, а восстановление системы займёт значительное время.
1-й вариант решения: Индекс размером до 10 Гб
Мы попробовали промежуточный вариант: выбрали максимальный размер каждого индекса 10 Гб. Следовательно, на каждом сервере получилось по 50-100 индексов, которые создаются в порядке поступления писем, а данные пользователя, таким образом, могут находиться в любом из индексов. Но письма часто содержат большое количество однотипной информации («привет», «пока», «@yandex.ru»), которая подходит под 46% всех запросов к поиску по Почте. Получалось, что ответ на такой запрос требовал поднять около 20% всех писем, хранящихся на сервере — это занимало десятки секунд.
2-й вариант решения: Префиксный индекс
Мы оставили максимальный размер индекса равным 10Гб, но перед каждым словом добавили ID пользователя. В результате каждый поиск сразу ограничивался количеством и размером писем в почтовом ящике текущего пользователя. Это снизило объем находимых данных и на порядок ускорило поиск. Но когда на диске – сотни индексов, то из-за большого числа дисковых операций поиск занимает несколько секунд. Наша же цель – десятые доли секунд.
3-й вариант решения: Шардирование по пользователям
Все индексы на сервере были разделены на 1000 сегментов (шардов). В каждом из них – от пяти до двадцати индексов размером до 1 Гб, и данные конкретного пользователя всегда находятся в определённом сегменте. В результате число дисковых операций было снижено до 20 раз по сравнению со вторым вариантом. Скорость поиска также увеличилась в разы. Так мы получили поиск за доли секунд.
Онлайн-индексация
Для того чтобы все поступающие письма практически сразу появлялись в результатах поиска, мы разработали специальный инкрементальный индекс в памяти. Особенность индекса в том, что в него можно добавлять по одному документу, а после добавления документ сразу появляется в поиске.
Процесс индексации выглядит так:
Поступающие письма попадают в инкрементальный индекс в памяти. Когда в памяти накапливается определенное количество писем или занят определенный объем, запускается процесс переноса данных из индекса в памяти в дисковый индекс. В этот же момент прекращается индексация в памяти №1 и создается индекс в памяти №2.
Конечно, это – лишь часть того, что мы делаем для улучшения качества нашего поиска по Яндекс.Почте. Может быть, у вас есть какие-то вопросы? Мы с радостью на них ответим.
Как устроен поиск по письмам в Яндекс.Почте
11 апреля 2011, 14:10