Каждый тариф, который мы продаём, от VPS за $3.29 до самого большого выделенного сервера, работает на NVMe. На странице с ценами это одна строка; эта статья — доказательства, которые за ней стоят. Мы прогнали одни и те же профили fio на наших боевых хостах, на массиве SATA SSD прошлого поколения и на VPS в том виде, в каком его получает клиент, и объясняем, какие из этих цифр ваша база данных действительно ощущает.
Методика
Во всех тестах использовались fio 3.36, прямой ввод-вывод (direct I/O), тестовый файл на 16 GB, чтобы обойти кэши, прогоны по 60 секунд после 30-секундного прогрева, результат усреднён по трём запускам. Три системы:
- NVMe-хост: два серверных NVMe-накопителя (PCIe 4.0, 3 DWPD) в программном зеркале; на этой конфигурации работают наши VPS-хосты, и она же используется по умолчанию на выделенных серверах.
- SATA-хост: четыре серверных SATA SSD в RAID 10 за аппаратным контроллером — конфигурация, от которой мы отказались в 2023 году.
- VPS-4: гостевая система KVM на NVMe-хосте со стандартным лимитом IOPS, замеры сделаны изнутри гостя через virtio-blk.
Цифры
| Профиль | NVMe-хост | SATA-хост | Гость VPS-4 |
|---|---|---|---|
| Случайное чтение 4k, QD1, задержка p50 | 68 µs | 142 µs | 95 µs |
| Случайное чтение 4k, QD1, задержка p99 | 110 µs | 390 µs | 210 µs |
| Случайное чтение 4k, QD32, IOPS | 612,000 | 178,000 | 40,000 (лимит) |
| Случайная запись 4k, QD1, задержка p99 (fsync) | 28 µs | 620 µs | 70 µs |
| Случайная запись 4k, QD32, IOPS | 380,000 | 72,000 | 20,000 (лимит) |
| Последовательное чтение, 1 MB, MB/s | 6,900 | 2,050 | 1,800 (лимит) |
| Последовательная запись, 1 MB, MB/s | 4,200 | 1,600 | 900 (лимит) |
| Смешанная нагрузка 70/30, 4k, QD16, IOPS | 420,000 | 105,000 | 32,000 (лимит) |
Столбец VPS ограничен политикой, а не железом: каждой гостевой системе выделяется лимит, чтобы ни один сосед не мог занять собой весь хост. Лимит здесь и есть суть сравнения. VPS-4 на своём потолке по задержке всё равно обгоняет весь массив SATA, а задержка — это та цифра, которая имеет значение.
Почему задержка, а не пропускная способность
Веб-запрос, обращающийся к базе данных, выполняет цепочку мелких зависимых чтений: страница индекса, затем страница таблицы (heap), затем ещё один индекс для соединения (join). Каждое из них — чтение 4k или 8k, которое должно завершиться, прежде чем начнётся следующее, поэтому время запроса — это сумма задержек, а не функция от пропускной способности. Запрос, затрагивающий 200 страниц, обходится в 14 ms на NVMe и в 28 ms на SATA по медиане, а разница на 99-м процентиле — это то, что пользователи замечают как «иногда тормозит».
С записью хуже. Каждая зафиксированная транзакция заканчивается вызовом fsync для журнала предзаписи (WAL). На массиве SATA это 620 µs на p99, на NVMe — 28 µs. Загруженный PostgreSQL, выполняющий 2,000 коммитов в секунду, тратит на ожидание fsync на SATA 1.2 секунды из каждой секунды, а на NVMe — 56 ms. Вот и вся разница между «нам нужен сервер побольше» и «всё в порядке».
Как это ощущает каждая база данных
- PostgreSQL: задержка коммита и случайное чтение страниц индекса. NVMe позволяет оставить
synchronous_commit = on, не платя за это; на SATA его отключают и жертвуют durability ради скорости. - MySQL / MariaDB: у redo-журнала InnoDB тот же профиль fsync, а doublewrite buffer заставляет SATA страдать вдвойне.
- Redis: в основном работает в памяти, но
appendfsync everysecна медленных дисках ненадолго блокирует работу и проявляется периодическими скачками задержки; на NVMe скачок исчезает. - ClickHouse, Elasticsearch: для слияний и больших сканирований важна последовательная пропускная способность; обе системы упираются почти в последовательный потолок хоста, и именно на такой нагрузке NVMe выделенного сервера без лимитов окупается по сравнению с лимитом VPS.
- SQLite: один пишущий процесс и fsync на каждую транзакцию; на SATA это ощущается медленно, а на NVMe выдерживает тысячи записей в секунду даже на VPS за $3.
Шумные соседи и лимиты
Альтернатива лимитам для каждой гостевой системы — медленные диски для всех; именно их обычно и выдают хосты с оверселлингом под вывеской «SSD-хранилище». Наш лимит задаётся для каждого тарифа, публикуется на странице с ценами и обеспечивается троттлингом ввода-вывода на уровне гипервизора так, что неиспользованная ёмкость возвращается в общий пул. На практике VPS-4 получает свой лимит целиком более чем в 99% времени; остальное — кратковременная конкуренция за диск во время резервного копирования у соседа, видимая как всплески p99 на несколько сотен микросекунд, а не секунд.
Если нужно снять потолок, честный ответ — выделенный сервер. Зеркальная пара NVMe отдаёт цифры первого столбца таблицы вам одному, а дополнение ZFS on root обменивает около 5% этой скорости на контрольные суммы и снапшоты — хорошая сделка для всего, что хранит важные для вас данные.
Как воспроизвести
apt install -y fio
fio --name=randread --filename=/srv/fio.test --size=16G --direct=1 --rw=randread \
--bs=4k --iodepth=1 --runtime=60 --time_based --ioengine=io_uring --group_reporting
fio --name=fsync --filename=/srv/fio.test --size=16G --direct=1 --rw=randwrite \
--bs=4k --iodepth=1 --fsync=1 --runtime=60 --time_based --ioengine=io_uring --group_reporting
Смотрите в выводе на clat percentiles, а не на крупный итоговый IOPS. После теста удалите тестовый файл: 16 GB — заметная часть диска VPS-1.
