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

milvus-logo
LFAI

Подготовка

  • Engineering
April 13, 2020
milvus

В этой статье мы расскажем о том, как векторные данные записываются в память Milvus и как эти записи поддерживаются.

Ниже приведены наши основные цели проектирования:

  1. Эффективность импорта данных должна быть высокой.
  2. Данные должны быть видны как можно быстрее после их импорта.
  3. Избегать фрагментации файлов данных.

Поэтому мы создали буфер памяти (буфер вставки) для вставки данных, чтобы уменьшить количество контекстных переключений случайных операций ввода-вывода на диске и в операционной системе для повышения производительности вставки данных. Архитектура хранения данных в памяти, основанная на MemTable и MemTableFile, позволяет нам более удобно управлять и сериализовать данные. Состояние буфера делится на Mutable и Immutable, что позволяет сохранять данные на диске, сохраняя доступность внешних сервисов.

Подготовка

Когда пользователь готов вставить вектор в Milvus, ему сначала нужно создать коллекцию (* Milvus переименовал таблицу в коллекцию в версии 0.7.0). Коллекция - это самая основная единица для записи и поиска векторов в Milvus.

Каждая Коллекция имеет уникальное имя и некоторые свойства, которые могут быть установлены, и векторы вставляются или ищутся на основе имени Коллекции. При создании новой Коллекции Milvus записывает информацию об этой Коллекции в метаданные.

Вставка данных

Когда пользователь отправляет запрос на вставку данных, данные сериализуются и десериализуются, чтобы попасть на сервер Milvus. Теперь данные записываются в память. Запись в память условно делится на следующие этапы:

2-data-insertion-milvus.png 2-data-insertion-milvus.png

  1. В MemManager найдите или создайте новую MemTable, соответствующую имени коллекции. Каждая MemTable соответствует буферу Коллекции в памяти.
  2. MemTable будет содержать один или несколько MemTableFile. Всякий раз, когда мы создаем новый MemTableFile, мы одновременно записываем эту информацию в Meta. Мы разделяем MemTableFile на два состояния: Mutable и Immutable. Когда размер MemTableFile достигнет порогового значения, он станет неизменяемым. Каждый MemTable может иметь только один Mutable MemTableFile для записи в любой момент времени.
  3. Данные каждого MemTableFile будут окончательно записаны в память в формате заданного типа индекса. MemTableFile - это самая базовая единица управления данными в памяти.
  4. В любой момент времени использование памяти для вставленных данных не будет превышать заданного значения (insert_buffer_size). Это происходит потому, что при каждом запросе на вставку данных MemManager может легко вычислить память, занимаемую MemTableFile, содержащимся в каждом MemTable, а затем скоординировать запрос на вставку в соответствии с текущим объемом памяти.

Благодаря многоуровневой архитектуре MemManager, MemTable и MemTableFile, вставка данных может лучше управляться и поддерживаться. Конечно, они могут делать и многое другое.

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

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

2-near-real-time-query-milvus.png 2-near-real-time-query-milvus.png

Сначала вставленные данные попадают в буфер вставки в памяти. Буфер будет периодически переходить из начального состояния Mutable в состояние Immutable в процессе подготовки к сериализации. Затем эти Immutable-буферы будут периодически сериализовываться на диск фоновым потоком сериализации. После размещения данных информация о заказе будет записана в метаданные. На этом этапе в данных можно производить поиск!

Теперь мы подробно опишем шаги, изображенные на рисунке.

Мы уже знаем процесс вставки данных в изменяемый буфер. Следующий шаг - переход от мутабельного буфера к мутабельному:

3-mutable-buffer-immutable-buffer-milvus.png 3-mutable-buffer-immutable-buffer-milvus.png

Immutable queue предоставит фоновому потоку сериализации неизменяемое состояние и MemTableFile, готовый к сериализации. Каждый MemTable управляет своей собственной неизменяемой очередью, и когда размер единственного изменяемого MemTableFile достигнет порогового значения, он попадет в неизменяемую очередь. Фоновый поток, отвечающий за ToImmutable, будет периодически вытаскивать все MemTableFiles из неизменяемой очереди, управляемой MemTable, и отправлять их в общую очередь Immutable. Следует отметить, что две операции - запись данных в память и изменение данных в памяти в состояние, которое не может быть записано, - не могут происходить одновременно, поэтому требуется общая блокировка. Однако операция ToImmutable очень проста и практически не вызывает задержек, поэтому влияние производительности на вставляемые данные минимально.

Следующий шаг - сериализация MemTableFile в очереди сериализации на диск. Эта операция в основном делится на три этапа:

4-serialize-memtablefile-milvus.png 4-serialize-memtablefile-milvus.png

Сначала фоновый поток сериализации будет периодически извлекать MemTableFile из неизменяемой очереди. Затем они сериализуются в сырые файлы фиксированного размера (Raw TableFiles). Наконец, мы запишем эту информацию в метаданные. Когда мы проводим векторный поиск, мы запрашиваем соответствующий TableFile в метаданных. Отсюда можно осуществлять поиск по этим данным!

Кроме того, согласно заданному index_file_size, после того как поток сериализации завершит цикл сериализации, он объединит несколько TableFiles фиксированного размера в TableFile, а также запишет эту информацию в метаданные. В это время TableFile может быть проиндексирован. Построение индекса также является асинхронным. Другой фоновый поток, отвечающий за построение индекса, будет периодически читать TableFile в состоянии ToIndex метаданных, чтобы выполнить соответствующее построение индекса.

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

Если вы хотите узнать больше, приглашаем вас ознакомиться с нашим исходным кодом или прочитать другие технические статьи о Milvus!

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started

Like the article? Spread the word

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