Общая архитектура
С взрывным ростом объема интернет-данных количество товаров и их категории в современных платформах электронной коммерции увеличиваются, с одной стороны, а с другой - возрастает сложность для пользователей в поиске нужных им товаров.
Vipshop является ведущим онлайн-ритейлером скидок на бренды в Китае. Компания предлагает высококачественные и популярные брендовые товары потребителям по всему Китаю со значительной скидкой от розничных цен. Чтобы оптимизировать процесс покупок для своих клиентов, компания решила создать персонализированную систему поисковых рекомендаций, основанную на ключевых словах запроса и портретах пользователей.
Основная функция системы поисковых рекомендаций для электронной коммерции - извлекать подходящие товары из большого количества продуктов и показывать их пользователям в соответствии с их поисковым намерением и предпочтениями. В этом процессе система должна рассчитать сходство между продуктами и поисковыми намерениями и предпочтениями пользователей и рекомендовать пользователям TopK продуктов с наибольшим сходством.
Такие данные, как информация о продукте, поисковые намерения и предпочтения пользователей, являются неструктурированными данными. Мы попытались рассчитать сходство таких данных с помощью CosineSimilarity(7.x) поисковой системы Elasticsearch (ES), но этот подход имеет следующие недостатки.
Длительное время отклика на вычисления - средняя задержка при получении результатов TopK из миллионов элементов составляет около 300 мс.
Высокая стоимость обслуживания индексов ES - один и тот же набор индексов используется как для векторов товарных признаков, так и для других связанных данных, что не облегчает построение индексов, но приводит к появлению огромного количества данных.
Мы попытались разработать собственный локально чувствительный хэш-плагин для ускорения вычисления CosineSimilarity в ES. Хотя производительность и пропускная способность были значительно улучшены после ускорения, задержка в 100+ мс все еще не соответствовала реальным требованиям онлайн-поиска товаров.
После тщательного исследования мы решили использовать Milvus, векторную базу данных с открытым исходным кодом, которая отличается поддержкой распределенного развертывания, многоязычными SDK, разделением чтения/записи и т. д. по сравнению с обычно используемым автономным Faiss.
Используя различные модели глубокого обучения, мы преобразуем массивные неструктурированные данные в векторы признаков и импортируем эти векторы в Milvus. Благодаря отличной производительности Milvus наша система рекомендаций по поиску в электронной коммерции может эффективно запрашивать TopK векторов, которые похожи на целевые векторы.
Общая архитектура
Архитектура](https://assets.zilliz.com/1_01551e7b2b.jpg "Архитектура.") Как показано на схеме, общая архитектура системы состоит из двух основных частей.
Процесс записи: векторы признаков элементов (далее - векторы элементов), сгенерированные моделью глубокого обучения, нормализуются и записываются в MySQL. Затем MySQL считывает обработанные векторы признаков предметов с помощью инструмента синхронизации данных (ETL) и импортирует их в векторную базу данных Milvus.
Процесс чтения: Поисковый сервис получает векторы характеристик предпочтений пользователя (далее - векторы пользователя) на основе ключевых слов запроса пользователя и его портретов, запрашивает похожие векторы в Milvus и выдает векторы TopK элементов.
Milvus поддерживает как инкрементное обновление данных, так и обновление данных целиком. При каждом инкрементном обновлении необходимо удалить существующий вектор элементов и вставить новый вектор элементов, что означает, что каждая вновь обновленная коллекция будет проиндексирована заново. Это лучше подходит для сценария с большим количеством чтений и меньшим количеством записей. Поэтому мы выбираем метод полного обновления данных. Более того, запись всех данных в несколько разделов занимает всего несколько минут, что эквивалентно обновлению практически в реальном времени.
Узлы записи Milvus выполняют все операции записи, включая создание коллекций данных, построение индексов, вставку векторов и т. д., и предоставляют публичные услуги с доменными именами записи. Узлы чтения Milvus выполняют все операции чтения и предоставляют публичные услуги с доменными именами "только чтение".
В то время как текущая версия Milvus не поддерживает переключение псевдонимов коллекций, мы внедряем Redis для плавного переключения псевдонимов между несколькими целыми коллекциями данных.
Узлу чтения требуется только считывать существующую информацию о метаданных и векторные данные или индексы из MySQL, Milvus и распределенной файловой системы GlusterFS, поэтому возможности чтения могут быть горизонтально расширены за счет развертывания нескольких экземпляров.
Детали реализации
Обновление данных
Сервис обновления данных включает в себя не только запись векторных данных, но и определение объема данных в векторах, построение индексов, предварительную загрузку индексов, управление псевдонимами и т. д. Общий процесс выглядит следующим образом. Процесс
Предположим, что перед построением полных данных CollectionA предоставляет сервис данных для общественности, и все используемые данные направляются в CollectionA (
redis key1 = CollectionA
). Целью построения целых данных является создание новой коллекции CollectionB.Проверка данных о товарах - проверка номера товара в таблице MySQL, сравнение данных о товарах с существующими данными в CollectionA. Оповещение может быть установлено в соответствии с количеством или процентом. Если заданное количество (процент) не будет достигнуто, все данные не будут построены, и это будет считаться неудачей этой операции построения, вызывая предупреждение; как только заданное количество (процент) будет достигнуто, начнется процесс построения всех данных.
Начало построения всех данных - инициализация псевдонима всех строящихся данных и обновление Redis. После обновления псевдоним всех собираемых данных направляется в CollectionB (
redis key2 = CollectionB
).Создание новой целой коллекции - определите, существует ли коллекция CollectionB. Если существует, удалите ее перед созданием новой.
Пакетная запись данных - вычислите ID раздела для каждого товара с его собственным ID, используя операцию модуло, и запишите данные в несколько разделов во вновь созданную коллекцию пакетно.
Построение и предварительная загрузка индекса - создание индекса (
createIndex()
) для новой коллекции. Файл индекса хранится на сервере распределенного хранения GlusterFS. Система автоматически имитирует запрос к новой коллекции и предварительно загружает индекс для разогрева запроса.Проверка данных коллекции - проверка количества элементов данных в новой коллекции, сравнение данных с существующей коллекцией и установка предупреждений на основе количества и процента. Если заданное количество (процент) не достигнуто, коллекция не будет переключена, а процесс создания будет считаться неудачным, что приведет к срабатыванию оповещения.
Переключение коллекции - управление псевдонимами. После обновления Redis весь используемый псевдоним данных направляется в коллекциюВ (
redis key1 = CollectionB
), исходный ключ Redis2 удаляется, и процесс сборки завершается.
Вызов данных
Данные раздела Milvus вызываются несколько раз для расчета сходства между векторами пользователя, полученными на основе ключевых слов запроса и портрета пользователя, и вектором элемента, и после объединения возвращаются векторы TopK элементов. Общая схема рабочего процесса выглядит следующим образом: В следующей таблице перечислены основные службы, участвующие в этом процессе. Видно, что средняя задержка для вызова векторов TopK составляет около 30 мс.
Сервис | Роль | Входные параметры | Выходные параметры | Задержка отклика |
---|---|---|---|---|
Получение векторов пользователя | Получение вектора пользователя | информация о пользователе + запрос | вектор пользователя | 10 мс |
Milvus Search | Вычисление сходства векторов и возвращение результатов TopK | вектор пользователя | вектор предмета | 10 мс |
Логика планирования | Одновременное извлечение и объединение результатов | Векторы элементов, отобранных по нескольким каналам, и оценка сходства | TopK элементов | 10 мс |
Процесс реализации:
- На основе ключевых слов запроса пользователя и его портрета модель глубокого обучения вычисляет вектор пользователя.
- Получение псевдонима коллекции всех используемых данных из Redis currentInUseKeyRef и получение Milvus CollectionName. Этот процесс является сервисом синхронизации данных, т. е. переключения псевдонима в Redis после обновления всех данных.
- Milvus вызывается одновременно и асинхронно с пользовательским вектором для получения данных из разных разделов одной коллекции, Milvus вычисляет сходство между пользовательским вектором и вектором элементов и возвращает TopK схожих векторов элементов в каждом разделе.
- Векторы TopK элементов, возвращенные из каждого раздела, объединяются и ранжируются в обратном порядке по расстоянию сходства, которое вычисляется с помощью внутреннего произведения IP (чем больше расстояние между векторами, тем больше они похожи). В итоге получаются векторы TopK элементов.
Перспективы
В настоящее время векторный поиск на основе Milvus может стабильно использоваться в сценариях поиска рекомендаций, а его высокая производительность дает нам больше возможностей для игры с размерностью модели и выбором алгоритма.
Milvus будет играть важную роль в качестве промежуточного программного обеспечения для большего числа сценариев, включая поиск по отзывам на главном сайте и рекомендации по всем сценариям.
Три наиболее ожидаемые функции Milvus в будущем следующие.
- Логика переключения псевдонимов коллекций - координация переключения между коллекциями без использования внешних компонентов.
- Механизм фильтрации - Milvus v0.11.0 поддерживает механизм фильтрации ES DSL только в автономной версии. Недавно выпущенный Milvus 2.0 поддерживает скалярную фильтрацию и разделение чтения/записи.
- Поддержка хранения для Hadoop Distributed File System (HDFS) - Milvus v0.10.6, который мы используем, поддерживает только файловый интерфейс POSIX, и мы развернули GlusterFS с поддержкой FUSE в качестве бэкенда хранения. Однако HDFS является лучшим выбором с точки зрения производительности и простоты масштабирования.
Извлеченные уроки и лучшие практики
- Для приложений, в которых основное внимание уделяется операциям чтения, развертывание разделения чтения и записи может значительно увеличить вычислительную мощность и повысить производительность.
- В Java-клиенте Milvus отсутствует механизм переподключения, поскольку клиент Milvus, используемый службой отзыва, находится в памяти. Нам приходится создавать собственный пул соединений, чтобы обеспечить доступность соединения между Java-клиентом и сервером с помощью проверки сердцебиения.
- На Milvus периодически возникают медленные запросы. Это связано с недостаточным прогревом новой коллекции. При симуляции запроса к новой коллекции индексный файл загружается в память, чтобы добиться прогрева индекса.
- nlist - это параметр построения индекса, а nprobe - параметр запроса. Вам необходимо подобрать разумное пороговое значение в соответствии с вашим бизнес-сценарием путем проведения тестовых экспериментов, чтобы сбалансировать производительность и точность поиска.
- Для сценария со статическими данными эффективнее сначала импортировать все данные в коллекцию, а затем строить индексы.
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word