🚀 Попробуйте Zilliz Cloud, полностью управляемый Milvus, бесплатно — ощутите 10-кратное увеличение производительности! Попробовать сейчас>

milvus-logo
LFAI

HomeBlogsИспользование базы данных векторов Milvus для запросов в режиме реального времени

Использование базы данных векторов Milvus для запросов в режиме реального времени

  • Engineering
April 11, 2022
Xi Ge

Cover image Изображение на обложке

Эта статья написана Си Гэ и переработана Анжелой Ни.

В предыдущем посте мы рассказали о вставке и сохранении данных в Milvus. В этой статье мы продолжим объяснять, как различные компоненты Milvus взаимодействуют друг с другом для выполнения запросов к данным в режиме реального времени.

Ниже перечислены некоторые полезные ресурсы, которые можно найти перед началом работы. Мы рекомендуем сначала прочитать их, чтобы лучше понять тему этого поста.

Загрузка данных в узел запроса

Перед выполнением запроса данные должны быть загружены в узлы запроса.

Существует два типа данных, загружаемых в узел запроса: потоковые данные из брокера журналов и исторические данные из объектного хранилища (также называемого ниже постоянным хранилищем).

Flowchart Блок-схема

Data coord отвечает за обработку потоковых данных, которые постоянно вставляются в Milvus. Когда пользователь Milvus обращается по адресу collection.load(), чтобы загрузить коллекцию, коорд запросов обращается к коорду данных, чтобы узнать, какие сегменты были сохранены в хранилище и какие контрольные точки им соответствуют. Контрольная точка - это метка, обозначающая, что сегменты, сохраненные до контрольной точки, потребляются, а сегменты после контрольной точки - нет.

Затем коорд запроса выводит стратегию распределения на основе информации из коорда данных: либо по сегментам, либо по каналам. Распределитель сегментов отвечает за распределение сегментов в постоянном хранилище (пакетных данных) между различными узлами запроса. Например, на изображении выше распределитель сегментов выделяет сегменты 1 и 3 (S1, S3) для узла запроса 1, а сегменты 2 и 4 (S2, S4) - для узла запроса 2. Распределитель каналов назначает различные узлы запроса для просмотра нескольких каналов манипулирования данными (DMChannels) в брокере журналов. Например, на изображении выше распределитель каналов назначает узел запроса 1 для просмотра канала 1 (Ch1), а узел запроса 2 - для просмотра канала 2 (Ch2).

При такой стратегии распределения каждый узел запроса загружает данные сегмента и просматривает каналы соответствующим образом. В узле запроса 1 на изображении исторические данные (пакетные данные) загружаются через выделенные S1 и S3 из постоянного хранилища. В то же время узел запроса 1 загружает инкрементные данные (потоковые данные), подписываясь на канал 1 в брокере журналов.

Управление данными в узле запроса

Узлу запроса необходимо управлять как историческими, так и инкрементными данными. Исторические данные хранятся в закрытых сегментах, а инкрементные данные - в растущих сегментах.

Управление историческими данными

Для управления историческими данными необходимо учитывать два момента: баланс нагрузки и восстановление работоспособности узла запроса.

Load balance Баланс нагрузки

Например, как показано на рисунке, узлу запроса 4 было выделено больше закрытых сегментов, чем остальным узлам запроса. Вполне вероятно, что это сделает узел запроса 4 узким местом, замедляющим весь процесс запроса. Чтобы решить эту проблему, системе необходимо распределить несколько сегментов узла запроса 4 между другими узлами запроса. Это называется балансировкой нагрузки.

Query node failover Обход отказа узла запроса

Другая возможная ситуация показана на рисунке выше. Один из узлов, узел запроса 4, внезапно выходит из строя. В этом случае нагрузку (сегменты, выделенные узлу запроса 4) необходимо передать другим работающим узлам запроса, чтобы обеспечить точность результатов запроса.

Инкрементное управление данными

Узел запроса просматривает DMChannels для получения инкрементных данных. В этот процесс вводится Flowgraph. Сначала он фильтрует все сообщения о вставке данных. Это делается для того, чтобы гарантировать, что будут загружены только данные в определенном разделе. Каждая коллекция в Milvus имеет соответствующий канал, который разделяется всеми разделами в этой коллекции. Поэтому, если пользователю Milvus нужно загрузить данные только в определенный раздел, то для фильтрации вставленных данных требуется блок-схема. В противном случае на узел запроса будут загружены данные из всех разделов коллекции.

После фильтрации инкрементные данные вставляются в растущие сегменты и далее передаются на временные узлы сервера.

Flowgraph Flowgraph

Во время вставки данных каждому сообщению о вставке присваивается временная метка. В канале DMChannel, показанном на рисунке выше, данные вставляются по порядку, слева направо. Временная метка для первого сообщения вставки равна 1, второго - 2, третьего - 6. Четвертое сообщение, отмеченное красным, не является сообщением вставки, а скорее сообщением timetick. Это означает, что вставленные данные, чьи временные метки меньше этой временной метки, уже находятся в журнале брокера. Другими словами, данные, вставленные после этого сообщения timetick, должны иметь временные метки, значения которых больше этого timetick. Например, на изображении выше, когда узел запроса воспринимает, что текущий таймстик равен 5, это означает, что все сообщения о вставке, чье значение временной метки меньше 5, загружены в узел запроса.

Узел времени сервера предоставляет обновленное значение tsafe каждый раз, когда получает метку времени от узла вставки. tsafe означает время безопасности, и все данные, вставленные до этого момента времени, могут быть запрошены. Например, если tsafe = 9, то все вставленные данные с временными метками меньше 9 могут быть запрошены.

Запрос в реальном времени в Milvus

Запрос в реальном времени в Milvus осуществляется с помощью сообщений запроса. Сообщения запросов вставляются в лог-брокер через прокси. Затем узлы запроса получают сообщения запроса, просматривая канал запроса в лог-брокере.

Сообщение запроса

Query message Сообщение запроса

Сообщение запроса включает в себя следующую важную информацию о запросе:

  • msgID: ID сообщения, идентификатор сообщения запроса, присвоенный системой.
  • collectionID: : ID коллекции для запроса (если задан пользователем).
  • execPlan: План выполнения в основном используется для фильтрации атрибутов в запросе.
  • service_ts: Временная метка сервиса будет обновляться вместе с tsafe, указанным выше. Временная метка сервиса означает, в какой момент времени находится сервис. Все данные, вставленные до service_ts, доступны для запроса.
  • travel_ts: Временная метка путешествия задает диапазон времени в прошлом. Запрос будет выполняться к данным, существующим в период времени, указанный travel_ts.
  • guarantee_ts: Временная метка гарантии задает период времени, после которого необходимо выполнить запрос. Запрос будет выполняться только в том случае, если service_ts > guarantee_ts.

Запрос в реальном времени

Query process Процесс запроса

При получении сообщения запроса Milvus сначала проверяет, превышает ли текущее время обслуживания, service_ts, гарантийную метку времени, guarantee_ts, в сообщении запроса. Если да, то запрос будет выполнен. Запросы выполняются параллельно как на исторических, так и на инкрементных данных. Поскольку потоковые и пакетные данные могут пересекаться, для отсеивания избыточных результатов запроса необходимо выполнить действие под названием "локальное сокращение".

Однако если текущее время обслуживания меньше, чем гарантийная метка времени в новом сообщении запроса, сообщение запроса становится неразрешенным и ожидает обработки до тех пор, пока время обслуживания не станет больше гарантийной метки времени.

Результаты запросов в конечном итоге передаются в канал результатов. Прокси получает результаты запроса из этого канала. Кроме того, прокси будет выполнять "глобальное уменьшение", поскольку он получает результаты от нескольких узлов запроса, и результаты запроса могут быть повторяющимися.

Чтобы убедиться, что прокси получил все результаты запроса, прежде чем вернуть их в SDK, в сообщении результата также будет храниться информация, включающая искомые закрытые сегменты, искомые DMC-каналы и глобальные закрытые сегменты (все сегменты на всех узлах запроса). Система может сделать вывод, что прокси получил все результаты запроса, только если выполняются оба следующих условия:

  • Объединение всех искомых запечатанных сегментов, записанных во всех сообщениях результатов, больше, чем глобальные запечатанные сегменты,
  • Все DMC-каналы в коллекции запрошены.

В конечном итоге прокси возвращает окончательные результаты после "глобального сокращения" в Milvus SDK.

О серии глубоких погружений

После официального объявления об общей доступности Milvus 2.0 мы организовали эту серию блогов Milvus Deep Dive, чтобы предоставить углубленную интерпретацию архитектуры и исходного кода Milvus. В этой серии блогов рассматриваются следующие темы:

Like the article? Spread the word

Продолжить чтение