Неподходящи ли POSIX для объектных хранилищ? Ответ, подкрепленный данными

Автор этого поста ставит под сомнение представленный в статье MinIO взгляд, который утверждает, что POSIX не является подходящим выбором для объектных хранилищ. Он провел комплексные тесты, включая MinIO s3fs-fuse и JuiceFS. Результаты показывают, что MinIO и JuiceFS демонстрируют отличную производительность, в то время как s3fs-fuse отстает. В сценариях перезаписи маленьких файлов, JuiceFS FUSE-POSIX превосходит другие решения.

Недавно я наткнулся на статью на блоге MinIO под названием “Наложение файловой системы на объектное хранилище – плохая идея. Вот почему.” Автор использовал s3fs-fuse в качестве примера, чтобы проиллюстрировать проблемы с производительностью, возникающие при доступе к данным MinIO с использованием методов Portable Operating System Interface (POSIX), подчеркивая, что производительность значительно отстает от прямого доступа к MinIO. Автор приписывает эти проблемы с производительностью встроенным недостаткам POSIX. Однако наш опыт несколько отличается от этого вывода.

POSIX представляет собой полезный и широко принятый стандарт. Разработка программного обеспечения, следуя POSIX, гарантирует совместимость и переносимость между различными операционными системами. Большинство приложений в разных отраслях придерживаются стандарта POSIX. С развитием облачных вычислений, больших данных и технологий AI, а также с увеличением объема хранимой информации, возрастает спрос на эластичные решения для хранения, такие как объектные хранилища. Несмотря на то, что объектные хранилища, такие как MinIO, предоставляют SDK на нескольких языках, многие традиционные приложения испытывают трудности с адаптацией своего кода для использования API объектного хранения. Это привело к тому, что различные продукты хранения реализовали интерфейсы POSIX поверх объектных хранилищ, чтобы удовлетворить эту неподатливую потребность.

Многие продукты в отрасли, такие как Ceph, JuiceFS и Weka, успешно реализовали интерфейсы POSIX на объектных хранилищах. Эти решения имеют большие пользовательские базы и множество успешных историй, и они хорошо себя зарекомендовали с точки зрения производительности.

Хотя действительно, что POSIX имеет значительную сложность, связанные с ним проблемы не являются непреодолимыми. Со уважением и желанием проверить эти утверждения, я создал тестовую среду, использовал те же примеры данных и методы тестирования, что и в статье о MinIO, и провел проверку.

Продукты по сравнению и тестовые цели

Для обеспечения всесторонней оценки я ввел JuiceFS в сравнение.

JuiceFS — это открытый, облачный, распределенный файловый системы. Он использует объектное хранилище в качестве слоя хранения данных и полагается на отдельную базу данных для хранения метаданных. Он предлагает различные методы доступа, включая POSIX API, S3 API, CSI Driver, HDFS API и WebDAV, а также уникальные механизмы разбиения на данные, кэширования и параллельного чтения/записи. JuiceFS является файловой системой, принципиально отличающейся от инструментов типа s3fs-fuse, которые просто преобразуют объектное хранилище в протоколы POSIX.

Введение JuiceFS в сравнение было направлено на объективную оценку преимуществ и недостатков реализации протоколов, таких как POSIX, поверх объектного хранилища.

I conducted the following two tests on MinIO, JuiceFS, and s3fs-fuse:

  • Написание файла размером 10 ГБ
  • Перезапись небольших файлов с помощью Pandas

Все три решения использовали экземпляр MinIO, развернутый на отдельных серверах, в качестве базового хранилища. Для тестовых образцов использовался файл размером 10 ГБ, который был таким же файлом CSV, упомянутым в статье о MinIO.

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

Настройка сервера и тестового окружения

Два идентичных конфигурированных облачных сервера:

  • Система: Ubuntu 22.04 x64
  • CPU: 8 ядер
  • RAM: 16 ГБ
  • SSD: 500 ГБ
  • Сеть: VPC

Информация для каждого сервера:

Server IP Purpose
Server A 172.16.254.18 Deploying the MinIO instance
Server B 172.16.254.19 As the test environment

Подготовка сервера A

1. Развернул MinIO на сервере A с помощью Docker, используя следующие команды:

# Создание отдельной директории и переход в нее.
mkdir minio && cd minio

# Создание файла конфигурации.
mkdir config
touch config/minio

2. Записал следующую информацию в файл config/minio:

MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=abc123abc
MINIO_VOLUMES="/mnt/data"

3. Создал контейнер MinIO:

sudo docker run -d --name minio \
  -p 9000:9000 \
  -p 9090:9090 \
  -v /mnt/minio-data:/mnt/data \
  -v ./config/minio:/etc/config.env \
  -e "MINIO_CONFIG_ENV_FILE=/etc/config.env" \
  --restart unless-stopped \
  minio/minio server --console-address ":9090"

4. На веб-консоли MinIO предварительно создал три бакета:

Bucket name Purpose
test-minio For testing MinIO
test-juicefs For testing JuiceFS
test-s3fs For testing s3fs-fuse

Подготовка сервера B

1. Скачал тестовый файл объемом 10 ГБ.

curl -LO https://data.cityofnewyork.us/api/views/t29m-gskq/rows.csv?accessType=DOWNLOAD

2. Установил клиент mc.

mc — это командная строка файлового менеджера, разработанная проектом MinIO. Он позволяет выполнять операции чтения и записи как на локальном диске, так и на объектном хранилище, совместимом с S3, в командной строке Linux. Команда mc cp предоставляет информацию о реальном времени прогресса и скорости копирования данных, что облегчает наблюдение за различными тестами.

Примечание: Для обеспечения справедливости тестов все три подхода использовали mc для тестов записи файлов.

# Скачать mc.
wget https://dl.min.io/client/mc/release/linux-amd64/mc

# Проверить версию mc.
mc -v
mc version RELEASE.2023-09-20T15-22-31Z (commit-id=38b8665e9e8649f98e6162bdb5163172e6ecc187)
Runtime: go1.21.1 linux/amd64

# Установить mc.
sudo install mc /usr/bin

# Установить псевдоним для MinIO.
mc alias set my http://172.16.254.18:9000 admin abc123abc

3. Скачал s3fs-fuse.

sudo apt install s3fs

# Проверить версию.
s3fs --version
Amazon Simple Storage Service File System V1.93 (commit:unknown) with OpenSSL

# Установить ключ доступа к объектному хранилищу.
echo admin:abc123abc >  ~/.passwd-s3fs

# Изменить разрешения на ключевой файл.
chmod 600  ~/.passwd-s3fs

# Создать директорию монтирования.
mkdir mnt-s3fs

# Монтировать объектное хранилище.
s3fs test-s3fs:/ /root/mnt-s3fs -o url=http://172.16.254.18:9000 -o use_path_request_style

4. Установил JuiceFS.

I used the official script to install the latest JuiceFS Community Edition.

# Однострочный скрипт установки
curl -sSL https://d.juicefs.com/install | sh -

# Проверить версию.
juicefs version
juicefs version 1.1.0+2023-09-04.08c4ae6

5. Я создал файловую систему. JuiceFS — это файловая система, которую необходимо создать перед использованием. Помимо объектного хранилища, ей требуется база данных в качестве движка метаданных. Она поддерживает различные базы данных. Здесь я использовал распространенный Redis в качестве движка метаданных.

Примечание: Я установил Redis на сервере A, доступный по 172.16.254.18:6379 без пароля. Процесс установки здесь опущен. Вы можете обратиться к документации Redis для подробностей.

# Создание файловой системы.
juicefs format --storage minio \
--bucket http://172.16.254.18:9000/test-juicefs \
--access-key admin \
--secret-key abc123abc \
--trash-days 0 \
redis://172.16.254.18/1 \
myjfs

6. Я получил доступ к JuiceFS, используя более распространенные методы POSIX и S3 API, и протестировал их производительность.

# Создание директорий монтирования.
mkdir ~/mnt-juicefs

# Монтирование файловой системы в режиме POSIX.
juicefs mount redis://172.16.254.18/1 /root/mnt-juicefs

# Доступ к файловой системе с использованием метода S3 API.
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=abc123abc
juicefs gateway redis://172.16.254.18/1 0.0.0.0:9000

# Установка псевдонима для S3 API JuiceFS в mc.
mc alias set juicefs http://172.16.254.18:9000 admin abc123abc

Примечание: шлюз JuiceFS также может быть развернут на сервере A или на любом другом сервере, доступном через интернет, поскольку он предоставляет сетевой API S3.

Тесты и результаты

Вот краткое изложение моих тестов и результатов:

Test MinIO S3FS-FUSE JuiceFS
(FUSE)
JuiceFS
(S3 gateway)
Writing a 10 GB file 0m27.651s 3m6.380s 0m28.107s 0m28.091s
Overwriting small files with Pandas 0.83s 0.78s 0.46s 0.96s

Тест 1: Запись файла объемом 10 ГБ

Этот тест был разработан для оценки производительности при записи больших файлов. Чем меньше времени требуется, тем лучше производительность. Я использовал команду time для измерения продолжительности операций записи, предоставляя три метрики:

  • реальное: Фактическое время от начала до конца выполнения команды. Оно включает все ожидания, такие как ожидание завершения операций ввода-вывода, ожидание переключения процессов и ожидание ресурсов.
  • пользователь: Время выполнения в пользовательском режиме, указывающее на время использования CPU для выполнения кода пользователя. Обычно оно представляет вычислительную нагрузку команды.
  • система: Время выполнения в режиме ядра, указывающее на время использования CPU для выполнения кода ядра. Обычно оно представляет нагрузку, связанную с системными вызовами, такими как файловый I/O и управление процессами.

MinIO

I ran the following command to perform a copy test:

time mc cp ./2018_Yellow_Taxi_Trip_Data.csv  my/test-minio/

Результаты записи файла размером 10 ГБ непосредственно в MinIO:

real    0m27.651s
user    0m10.767s
sys 0m5.439s

s3fs-fuse

I ran the following command to perform a copy test:

time mc cp ./2018_Yellow_Taxi_Trip_Data.csv /root/mnt-s3fs/

Результаты записи файла размером 10 ГБ непосредственно в s3fs-fuse:

real 3m6.380s
user 0m0.012s
sys 0m5.459s

Примечание: Хотя время записи для s3fs-fuse составило 3 минуты и 6 секунд, отказов записи, как описано в статье MinIO, не было.

JuiceFS

I tested the performance of JuiceFS for large file writes using both the POSIX and S3 API methods:

# Тест записи POSIX
time mc cp ./2018_Yellow_Taxi_Trip_Data.csv /root/mnt-juicefs/

# Тест записи API S3
time mc cp ./2018_Yellow_Taxi_Trip_Data.csv  juicefs/myjfs/

Результаты записи файла размером 10 ГБ через POSIX в JuiceFS:

real    0m28.107s
user    0m0.292s
sys 0m6.930s

Результаты записи файла размером 10 ГБ через API S3 в JuiceFS:

real    0m28.091s
user    0m13.643s
sys 0m4.142s

Сводка результатов записи больших файлов

На следующем рисунке показаны результаты теста:

Large file write results (lower is better)

Результаты теста показывают, что как прямая запись в MinIO, так и в JuiceFS обеспечили сравнимую производительность, завершив задачу примерно за 30 секунд. В сравнении с этим, s3fs-fuse занял более 3 минут для записи файла размером 10 ГБ, что было примерно в шесть раз медленнее, чем у первых двух.

При написании больших файлов, mc использует API Multipart для загрузки файлов частями в интерфейс S3. Напротив, s3fs-fuse может писать в POSIX только в одном потоке. JuiceFS также автоматически делит большие файлы на части и записывает их параллельно в MinIO во время последовательных записей, обеспечивая производительность на уровне прямых записей MinIO. S3FS, с другой стороны, сначала записывает на кэш-диск в одном потоке, а затем загружает файл частями в MinIO, что приводит к более длительному времени записи.

Основываясь на расчете, что на запись файла размером 10 ГБ ушло 30 секунд, средняя скорость составила 333 МБ/с. Это было ограничено пропускной способностью SSD облачных серверов. Эти результаты тестов показали, что как MinIO, так и JuiceFS могут максимально использовать пропускную способность локальных SSD, и их производительность улучшится с улучшением облачных дисков сервера и пропускной способности сети.

Тест 2: Перезапись Маленьких Файлов С Помощью Pandas

Этот тест оценивал производительность систем объектного хранения в сценариях перезаписи маленьких файлов. Тестовые скрипты для каждого программного обеспечения немного различались. Вы можете найти все скрипты кода здесь.

MinIO

I got the test script and ran the test:

# Получить тестовый скрипт.
curl -LO https://gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-minio.py

# Запустить тест.
python3 pandas-minio.py

Результат был следующим:

Execution time: 0.83 seconds

s3fs-fuse

I got the test script and ran the test:

# Получить тестовый скрипт.
curl -LO gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-s3fs.py

# Запустить тест.
python3 pandas-s3fs.py

Тестовый результат был следующим:

Execution time: 0.78 seconds

JuiceFS POSIX

I got the test script and ran the test:

# Получить тестовый скрипт.
curl -LO gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-juicefs-posix.py

# Запустить тест.
python3 pandas-juicefs-posix.py

Результат теста был следующим:

Execution time: 0.43 seconds

API JuiceFS S3

I got the test script and ran the test:

# Получить сценарий теста.
curl -LO https://gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-juicefs-s3api.py

# Запустить тест.
python3 pandas-juicefs-s3api.py

Результат теста был следующим:

Execution time: 0.86 seconds

Сводка о перезаписи малых файлов Pandas

На следующем рисунке показаны результаты теста:

Pandas overwrite results (lower is better)

В этом тесте JuiceFS FUSE-POSIX продемонстрировал самую быструю скорость, почти в два раза быстрее, чем другие решения. MinIO, s3fs-fuse и JuiceFS S3 Gateway продемонстрировали схожие показатели производительности. С точки зрения перезаписи малых файлов интерфейс POSIX оказался более эффективным, обеспечивая лучшую производительность, чем интерфейсы объектного хранилища.

Проблемы и анализ

Проблема 1: Почему S3FS был таким медленным?

Анализ: По данным теста, видно, что при записи одного и того же 10 ГБ файла, S3FS занял 3 минуты, в то время как MinIO и JuiceFS оба выполнили задачу примерно за 30 секунд. Это существенное различие в производительности было в основном связано с различными техническими реализациями. Когда s3fs-fuse записывает файл, он сначала записывает файл в локальный временный файл, а затем загружает его в объектное хранилище частями. Если недостаточно местного дискового пространства, он загружает синхронно. Требуется копировать данные между локальным диском и хранилищем S3. Следовательно, большие файлы или значительное количество файлов приводят к снижению производительности.

Более того, S3FS зависит от возможностей управления метаданными базового объектного хранилища. При работе с большим количеством файлов частые взаимодействия с объектным хранилищем для получения метаданных существенно влияют на производительность. Проще говоря, чем больше размер файлов и общее количество файлов, записанных в S3FS, тем больше пропорциональные накладные расходы на производительность.

Вопрос 2: Почему JuiceFS быстрее?

Анализ: В тесте и JuiceFS, и S3FS использовали FUSE для чтения и записи. JuiceFS полностью использовал пропускную способность диска, как MinIO, но не столкнулся с проблемами производительности, как S3FS.

Ответ кроется в их соответствующих технических архитектурах. Хотя данные обрабатываются через слой FUSE при записи файлов, JuiceFS использует высокую степень параллелизма, кэширование и разбиение данных для снижения коммуникационных накладных расходов между слоем FUSE и базовым объектным хранилищем. Это позволяет JuiceFS обрабатывать большее количество запросов на чтение и запись файлов одновременно, сокращая время ожидания и задержку передачи.

Кроме того, JuiceFS использует специальную базу данных (в данном случае, Redis) для управления метаданными. При работе с особенно большим количеством файлов независимый движок метаданных может эффективно облегчить нагрузку, обеспечивая более быстрое местонахождение файлов.

Заключение

Тесты выше демонстрируют, что использование объектного хранилища в качестве основы и реализация интерфейса POSIX поверх него не обязательно приводит к потере производительности. Независимо от того, пишутся ли большие или маленькие файлы, JuiceFS демонстрирует производительность, сопоставимую с прямыми записями MinIO, без какого-либо снижения производительности базового объектного хранилища из-за доступа POSIX. Более того, в плане перезаписи таблиц Pandas, производительность JuiceFS FUSE-POSIX остается стабильной и даже превышает MinIO почти вдвое.

Результаты тестов показывают, что некоторые программы, такие как s3fs-fuse, могут испытывать снижение производительности при преобразовании между API S3 и интерфейсами POSIX. Хотя это может быть удобным инструментом для временного доступа к S3, для стабильного и высокопроизводительного долгосрочного использования необходимо тщательно исследовать и проверять, чтобы выбрать более подходящие решения.

Для простого архивирования неструктурированных файлов, прямое использование MinIO или облачного объектного хранилища является хорошим выбором. Однако для сценариев, связанных с крупномасштабным хранением и обработкой данных, таких как обучение моделей AI, анализ больших данных, устойчивость данных Kubernetes и другие часто выполняемые операции чтения и записи, JuiceFS предоставляет превосходную производительность благодаря независимому управлению метаданными, возможностям параллельного чтения и записи, а также механизмам кэширования. Это высокопроизводительное решение файловой системы, которое стоит рассмотреть.

Source:
https://dzone.com/articles/is-posix-really-unsuitable-for-object-stores-a-dat