Key-value для хранения метаданных в СХД. Тестируем выделенные базы данных



    В этой статье мы продолжаем рассказывать о том, как можно хранить метаданные в СХД при помощи баз данных key-value.

    На этот раз в центре нашего внимания выделенные БД: Aerospike и RocksDB. Описание значимости метаданных в СХД, а также результаты тестирования встроенных БД можно посмотреть тут.

    Параметры тестирования key-value БД


    Кратко напомним основные параметры, по которым мы проводили тестирование (подробности в предыдущей статье).

    Основной workload — Mix50/50. Дополнительно оценивали: RR, Mix70/30 и Mix30/70.

    Тестирование проводили в 3 этапа:

    1. Заполнение БД — заполняем в 1 поток БД до необходимого количества ключей.
      1.1 Сбрасываем кэши! Иначе тесты будут нечестными: БД обычно пишут данные поверх файловой системы, поэтому срабатывает кэш операционной системы. Важно сбрасывать его перед каждым тестом.
    2. Тесты на 32 потока — прогоняем workload'ы
      2.1 Random Read
      • Сбрасываем кэши!
      2.2 Mix70/30
      • Сбрасываем кэши!
      2.3 Mix50/50
      • Сбрасываем кэши!
      2.4 Mix30/70
      • Сбрасываем кэши!
    3. Тесты на 256 потоков.
      3.1 То же самое, что и на 32 потока.

    Измеряемые показатели


    • Пропускная способности/throughput (IOPS/RPS — кто какие обозначения больше любит).
    • Задержки/latency (msec):
      • Min.
      • Max.
      • Среднее квадратическое значение — более показательное значение, чем среднее арифметическое, т.к. учитывает квадратичное отклонение.
      • Перцентиль 99.99.

    Тестовое окружение


    Конфигурация:
    CPU: 2x Intel Xeon E5-2620 v4 2.10GHz
    RAM: 16GB
    Disk: [2x] NVMe HGST SN100 1.5TB
    OS: CentOS Linux 7.2 kernel 3.11
    FS: EXT4

    Объем доступной RAM регулировался не физически, а программно — часть заполнялась искусственно скриптом на Python, а остаток был свободен для БД и кэшей.

    Выделенные БД. Aerospike


    Чем Aerospike отличается от движков, которые мы до этого тестировали?

    • Индекс в RAM
    • Использование RAW дисков (= нет ФС)
    • Не дерево, а хэш.

    Так сложилось, что в индексе Aerospike на каждый ключ хранится 64Б (а сам ключ у нас всего 8Б). При этом индекс всегда полностью должен быть в RAM.

    Это означает, что при нашем количестве ключей индекс не поместится в памяти, которую мы выделяем. Надо уменьшить количество ключей. И наши данные это позволяют!


    Рис. 1. Схема упаковки 1


    Рис. 2. Схема упаковки 2

    Итак, с помощью такой упаковки мы уменьшили количество ключей в 4 раза. Таким же образом можем уменьшить их количество в k раз. Тогда размер значения будет 16*k Б.

    Тестирование. 17 млрд ключей


    Чтобы индекс Aerospike на 17 млрд ключей (17 млрд сопоставлений lba->metadata) поместился в RAM, надо упаковать это всё в 64 раза.

    В итоге получим 265 625 000 ключей (каждому из ключей будет соответствовать значение размером 1024Б, содержащее 64 экземпляра метаданных).

    Тестировать будем с помощью YCSB. Он не выдаёт среднюю квадратическую задержку, поэтому её не будет на графиках.

    Заполнение


    Aerospike показал неплохой результат на заполнение. Ведёт себя очень стабильно.

    Но заполнение проводилось в 16 потоков, а не в один, как было с движками. В один поток Aerospike выдавал около 20k IOPS. Скорее всего, дело в бенчмарке (т.е. в один поток бенчмарк просто не «выжимает» БД). Либо же Aerospike любит много потоков, а в один не готов выдавать большую пропускную способность.


    Рис. 3. Производительность заполнения базы

    Максимальная задержка также держалась на примерно одинаковом уровне на протяжении всего заполнения.


    Рис. 4. Latency заполнения базы

    Тесты


    Здесь важно отметить, что на этих графиках нельзя напрямую сравнивать Aerospike и RocksDB, т.к тесты проводились в разных условиях и разными бенчмарками – Aerospike использовался «с упаковкой», а RocksDB — без.

    Также стоит учесть, что 1 IO у Aerospike = извлечение 64 значений (экземпляров метаданных).
    Результаты RocksDB здесь приведены в качестве опорных.


    Рис. 5. Сравнение Aerospike и RocksDB.100% Read


    Рис. 6. Сравнение Aerospike и RocksDB. Mix 70%/30%


    Рис. 7. Сравнение Aerospike и RocksDB Mix 50%/50%


    Рис. 8. Сравнение Aerospike и RocksDB Mix 30%/70%

    В итоге запись на малом количестве потоков получилась медленнее, чем у RocksDB (при этом следует помнить, что в случае Aerospike за один раз записывается сразу 64 значения).

    Но на большом количестве потоков Aerospike всё же выдаёт более высокие значения.


    Рис. 9. Aerospike. Latency Read 100%

    Тут мы, наконец-то, смогли получить приемлемый уровень задержки. Но только в тесте на чтение.


    Рис. 10. Aerospike.Latency Mix 50%/50%

    Теперь можно обновить список выводов:

    • Запись + мало потоков => WiredTiger
    • Запись + много потоков => RocksDB
    • Чтение + DATA > RAM => RocksDB
    • Чтение + DATA < RAM => MDBX
    • Много потоков + DATA > RAM + Упаковка => Aerospike

    Итоговый вывод по выбору БД для метаданных: в таком виде ни один из претендентов не достигает нужных нам показателей. Ближе всех Aerospike.

    Ниже мы расскажем о том, что с этим можно делать, и что нам дает хранение данных в прямой адресации.

    Прямая адресация. 137 млрд ключей


    Рассмотрим системы хранения объемом 512 ТВ. Метаданные такой системы хранения как раз помещаются на одну NVME и соответствуют 137 млрд ключей для key-value базы данных.

    Рассмотрим простейшую реализацию прямой адресации. Для этого на одном узле создадим SPDK NVMf таргет, на другом узле возьмем локальную NVMe и этот NVMf таргет и объединим их в логический RAID1.

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

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

    Таблица 1. Тестирование прямой адресации
    rand read 4k (IOPS) rand write 4k (IOPS) rand r/w 50/50 4K(IOPS) rand r/w 70/30 4K(IOPS) rand r/w 30/70 4K(IOPS)
    spdk 760 — 770 K 350 — 360 K 400 — 410 K 520 — 540 K 410 — 450 K
    lat (ms) avg/max 0.3 / 5 0.4 / 23 0.3 / 19 0,5 / 21 1,2 / 28

    Теперь протестируем Aerospike в аналогичной конфигурации, где 137 млрд ключей как раз также помещаются на одну NVMe и реплицируются на другую NVMe.

    Тестируем с помощью «родного» бенчмарка Aerospike. Берем два бенчмарка – каждый на своем узле – и 256 потоков, чтобы выжать максимальную производительность.

    Получаем следующие результаты:

    Таблица 2. Тестирование Aerospike c репликацией
    R/W IOPS >1ms >2ms >4ms 99.99 lat <=
    100/0 635000 7% 1% 0% 50
    70/30 425000 8% 3% 1% 50
    50/50 342000 8% 4% 1% 50
    30/70 271000 8% 4% 1% 40
    0/100 200000 0% 0% 0% 36

    Ниже приведены результаты тестирования без репликации, один бенчмарк в 256 потоков.

    Таблица 3. Тестирование Aerospike без репликации
    R/W IOPS <=1ms >1ms >2ms 99.99 lat <=
    100/0 413000 99% 1% 0% 5
    70/30 376000 95% 5% 2% 7
    50/50 360000 92% 8% 3% 8
    30/70 326000 93% 7% 3% 8
    0/100 260000 94% 6% 2% 5

    Заметим, что Aerospike c репликацией работает не хуже, а даже лучше. При этом возрастает latency по сравнению с тестированием Aerospike без репликации.

    Также приведем результаты тестирования RocksDB без репликации (у RocksDB нет родной встроенной репликации) своим бенчмарком в 256 потоков, 137 млрд ключей с упаковкой.

    Таблица 4. Тестирование RocksDB без репликации
    R/W IOPS <=1ms >1ms >2ms 99.99 lat <=
    100/0 444000 93% 7% 2% 300
    70/30 188000 86% 14% 4% 2000
    50/50 107000 75% 25% 3% 1800
    30/70 73000 85% 15% 0% 1200
    0/100 97000 74% 26% 17% 2500

    Выводы


    • RocksDB «c упаковкой» не проходит тесты по latency
    • Aerospike c репликацией почти удовлетворяет критериям
    • Простейшая реализация прямой адресации соответствует всем критериям по производительности и задержкам.

    Постскриптум. Ограничения


    Отметим важные параметры, которые остались за рамками данного исследования:

    • Файловая система (ФС) и её настройки
    • Настройки виртуальной памяти
    • Настройки БД.

    1. ФС и её настройки


    • Есть мнение, что для RocksDB, например, хорошо подходит F2FS или XFS
    • Также выбор ФС зависит от того, какие накопители используются в системе
    • Размер страницы (блока) ФС

    2. Настройки виртуальной памяти


    • Можно почитать тут.

    3. Настройки БД


    • MDBX. От разработчика этого движка была получена рекомендация попробовать другой размер страниц в движке: 2 килобайта или размер кластера в NVME. В целом этот параметр важен и у других БД (даже в Aerospike).
    • WiredTiger. Кроме параметра cache_size, который мы меняли, есть ещё масса параметров. Читать тут.
    • RocksDB.
      • Можно попробовать Direct IO: т.е. общение с диском, минуя page cache. Но тогда, скорее всего, надо будет увеличить block cache, встроенный в RocksDB. Об этом тут.
      • Есть информация о том, как настроить RocksDB для NVME. Тут, кстати, используется XFS.
    • Aerospike. Также имеет много настроек, но их тюнинг за несколько часов не принёс ощутимых результатов.
    RAIDIX 44,07
    Компания
    Поделиться публикацией
    Комментарии 2
    • 0
      интересная статья, спасибо!
      • 0
        у меня очень хорошие результаты получались с LMDB. Читающие потоки не блокируются пишущими, а пишущие блокируют только друг друга. Если обновления вести аккуратно, желательно в одном потоке, то получается и космическая скорость чтения и приемлемлемая скорость обновления. Имеет смысл если операций чтения на порядки больше записи.
        К сожалению — это только локальное (встроенное) K-V хранилище. Если нужна распределенность и удаленность — вроде есть memcachedb ( github.com/LMDB/memcachedb ) c вариантом использования LMDB в качестве хранилища, но мне не довелось его потестировать. Собственно вопрос — может, вы сможете сравнить что у вас получится в случае memcachedb?

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

        Самое читаемое