Введение в архитектуру Milvus
В ходе опроса более 1200 пользователей мы выявили одну ключевую повторяющуюся проблему: масштабируемость. Как мы можем масштабировать наши векторные операции? Этот вопрос привёл к разработке Milvus как распределённой системы. Векторные базы данных, в отличие от традиционных баз данных, имеют другие требования к использованию. Три основных отличия побудили нас создать облачно-нативную векторную базу данных с нуля.
Во-первых, векторные данные не требуют сложных транзакций.
Во-вторых, разнообразие сценариев использования требует настраиваемого компромисса между производительностью и согласованностью.
В-третьих, некоторые операции с векторными данными являются вычислительно затратными, что требует эластичного распределения ресурсов.
Milvus достигает горизонтального масштабирования благодаря продуманной архитектуре распределённой системы. Хотя базы данных с одним экземпляром могут масштабироваться до определённого предела, вскоре они упираются в ограничения аппаратного обеспечения. Возможность горизонтального масштабирования Milvus решает эту проблему, позволяя базе данных расширяться на несколько экземпляров. Существует два способа горизонтально масштабировать базу данных: напрямую встроить эту функциональность в базу данных или вручную реализовать процессы масштабирования.
В Milvus функциональность масштабирования встроена в систему. Хотя вы можете управлять масштабированием самостоятельно, это не идеальное решение, если только ваша критически важная работа не связана с масштабированием баз данных. Рассмотрим три архитектурных решения и два варианта проектирования поиска, которые делают Milvus настолько масштабируемым.
Облачно-нативная системная архитектура
Большинство команд разработки программного обеспечения больше не разворачивают приложения на серверах в серверной комнате. Почему? Доступные публичные облака (AWS, Azure, GCP и т. д.) позволяют командам разработки двигаться быстрее. Milvus создан так, чтобы использовать преимущества гибкости, которую даёт работа в облаке.
Milvus содержит четыре уровня: доступ, координация, рабочие узлы и хранилище. Узлы доступа без состояния предоставляют доступ к системе. Рабочие узлы и координаторы спроектированы по serverless-шаблону. Координаторы с состоянием запускают и останавливают рабочие узлы без состояния по мере необходимости. Уровень хранилища хранит векторные данные и всю необходимую информацию для функционирования системы.
Разделение ответственности
При работе с векторной базой данных существуют три основные области ответственности: запросы, загрузка данных и индексирование. Эти три функциональности всегда будут масштабироваться в разной степени и в разное время. Milvus предоставляет три разных типа узлов, которые могут масштабироваться независимо.
Узлы запросов обрабатывают функциональность запросов, а значит, они должны иметь достаточно памяти для хранения индексов в памяти для нескольких сегментов. Сегменты — это блоки данных заранее заданного размера, которые Milvus использует для эффективности и масштабируемости. Узлы запросов также помогают распараллеливать поиск, используя часть своих вычислительных ресурсов и памяти для делегирования, агрегации и обработки результатов поиска из нескольких сегментов, многие из которых могут находиться на других узлах.
По мере поступления данные попадают как в узлы запросов, так и в узлы данных. Эти узлы удерживают данные в растущих сегментах, которые ещё не достигли своего предельного размера. После того как сегмент достигает ёмкости, узел запросов освобождает эти данные и заменяет их сгенерированным индексом.
Узлы данных обрабатывают загрузку данных. После того как сегмент достигает своего предельного размера на узле данных, он становится «запечатанным». Затем запечатанные сегменты сбрасываются в постоянное хранилище из узлов данных и запросов. После того как данные сброшены на уровень хранилища, координаторы уведомляют узел индексирования.
Узлы индексирования строят индексы. Когда узел индексирования получает уведомление, он считывает сегмент данных с уровня хранилища. Такая схема естественным образом позволяет нам работать с меньшим объёмом данных при создании индекса. Поскольку узел индексирования считывает данные из хранилища, он может считывать только те атрибуты, которые нужны ему для построения индексов.
Согласованность записи в крупном масштабе
Естественная часть масштабирования — столкновение с проблемами согласованности. Как только вы запускаете вторую реплику или экземпляр Milvus или любой другой системы баз данных, вы сразу сталкиваетесь с проблемой согласованности данных. Вы должны обеспечить общесистемное соглашение о том, насколько согласованными должны быть данные.
В Milvus встроено множество возможностей для настройки согласованности данных. Milvus — это pub/sub-система. Блок хранения сообщений выступает в роли системы публикации, проставляя временную метку для каждого фрагмента данных, который через него проходит. Затем узлы запросов и данных считывают этот журнал публикаций как подписчики.
Масштабирование записи подразумевает масштабирование количества шардов, выступающих в роли писателей. По мере поступления данных их ID хешируется, и хеш определяет, какой шард будет записывать этот фрагмент данных.
Сегменты данных для параллельного поиска
Как упоминалось ранее, Milvus создает отдельные индексы на заранее заданных объемах данных, называемых «сегментами». По умолчанию Milvus создает сегменты на 512MB данных, что можно изменить в соответствии с вашими потребностями.
Зачем мы создаем сегменты и строим индексы таким образом? Для большей гибкости, масштабируемости и простоты изменения. Индексы — это способы доступа к данным. Представьте, что вы строите индекс на некотором исходном наборе данных. В реальном сценарии ваши данные со временем меняются, поэтому вам придется продолжать добавлять данные. Поскольку исходный индекс был построен только на исходных данных, он не помогает с новыми данными.
Рациональным решением этой проблемы индексирования было бы непрерывное построение новых индексов через некоторый заранее заданный интервал (например, по объему добавленных новых данных). Milvus реализует это решение на нескольких экземплярах и репликах.
Такая организация сегментов обеспечивает эффективное решение проблемы неэффективного индексирования и делает запросы более масштабируемыми. Поскольку индексы, построенные на отдельных сегментах данных, не зависят друг от друга, мы можем искать по ним параллельно, ограничиваясь только аппаратным обеспечением.
Выбор большего размера сегмента повышает эффективность каждой операции поиска; однако важно отметить, что этот выбор также приводит к увеличению затрат, связанных с компакцией и перестроением индекса.
Поиск по метаданным с предварительной фильтрацией
Фильтрация метаданных — важная функция для многих пользователей. Эта функция позволяет искать только векторы за определенные даты, от определенных авторов или с определенными значениями атрибутов. При проектировании приложения векторного поиска вы можете разместить фильтрацию метаданных либо до, либо после функциональности векторного поиска.
Перед выполнением векторного поиска Milvus генерирует битовую маску по метаданным. Эта операция предварительной фильтрации выполняется за линейное время. Milvus один раз просматривает данные и проверяет, соответствуют ли метаданные заданному выражению фильтра. Предварительная фильтрация метаданных уменьшает объем данных, подвергаемых векторному поиску, что делает операцию векторного поиска более эффективной.
В предстоящем релизе Milvus 2.4 мы будем поддерживать инвертированный индекс с tantivy, и скорость предварительной фильтрации резко возрастет.
Резюме
Milvus использует архитектуру распределенной системы, состоящую из четырех уровней: доступа, координации, рабочих узлов и хранения. Учитывая разнообразные варианты использования векторных баз данных, необходима адаптируемая и развивающаяся инфраструктура. Milvus моделирует свой компонент приема данных в соответствии с этим требованием как pub/sub (publish-subscribe) систему.
Моделирование приема данных как pub/sub-сервиса дает нам гибкость, позволяя использовать парадигму развязанного сервиса, и помогает с согласованностью данных. Сервис «публикации» помечает каждый фрагмент данных временной меткой как часть функциональности согласованности.
Что касается трех аспектов (запросов, приема данных и индексирования) в векторной базе данных, Milvus разделяет их все. У каждой из трех операций есть свой выделенный узел. Вы можете независимо запускать и останавливать узлы, что позволяет Milvus масштабироваться в зависимости от объема ваших данных и характера использования.
Обеспечение согласованности данных — одна из самых сложных задач по мере роста объема ваших данных. Milvus решает эту проблему с помощью «шардов». Поступающие данные хешируются, а затем распределяются по шардам на основе их хеша. Milvus имеет настраиваемую согласованность с четырьмя уровнями на выбор, позволяя находить компромисс между скоростью ответа поиска и скоростью репликации данных между множеством экземпляров базы данных.
Запись данных в масштабе использует несколько шардов. Чтение данных в масштабе использует сегменты. Индексы строятся на отдельных сегментах. Теперь каждый сегмент можно искать параллельно во время выполнения запроса, что значительно сокращает время поиска для больших объемов данных.
При поиске данных вы, вероятно, захотите иметь возможность каким-либо образом их фильтровать. Milvus реализует фильтрацию метаданных как операцию предварительной фильтрации. Затем он применяет битовую маску к набору данных во время векторного поиска и пропускает любые векторы, которые не подходят. Такой подход может значительно сократить время поиска, если отфильтровывается много векторов.
Уникальная архитектура Milvus предоставляет множество преимуществ, особенно горизонтальное масштабирование. Она тщательно спроектирована как облачно-нативная векторная база данных для быстрого горизонтального масштабирования при сохранении оптимальной производительности. Преднамеренно разобщенный архитектурный дизайн упрощает развитие Milvus со временем и обеспечивает гибкость. Эта адаптивность оказывается критически важной с учетом растущей значимости векторных баз данных и расширяющегося спектра вариантов их использования.
Читать далее

Introducing Loon: A New Storage Engine for Vector Data That Never Stops Changing
Loon is a new storage engine for Milvus 3.0 and Zilliz Vector Lakebase, built to manage evolving vector datasets with ColumnGroups, row ID alignment, and Manifests.

Introducing Zilliz Cloud Global Cluster: Region-Level Resilience for Mission-Critical AI
Zilliz Cloud Global Cluster delivers multi-region resilience, automatic failover, and fast global AI search with built-in security and compliance.

The Real Bottlenecks in Autonomous Driving — And How AI Infrastructure Can Solve Them
Autonomous driving faces a data bottleneck. Learn how AI-native vector databases like Zilliz solve scale, cost, and insight challenges across AV pipelines.



