LINUX.ORG.RU

Второй кандидат в релизы libmdbx v1.0 после пяти лет разработки

 , , , ,


4

4

Библиотека libmdbx является существенно переработанным потомком LMDB — предельно высокопроизводительной, компактной встраиваемой базой данных класса ключ-значение. Текущая версия v0.5 является техническим релизом, отмечает завершение каких-либо доработок и переход к фазе публичного финального тестирования и стабилизации, с последующем формированием первого полноценного релиза библиотеки.

LMDB является достаточно известной транзакционной встраиваемой СУБД класса «ключ-значение» на основе дерева B+ без упреждающей журнализации, которая позволяет рою многопоточных процессов конкурентно и предельно эффективно работать с локально-разделяемой (не сетевой) БД. В свою очередь MDBX быстрее и надежнее LMDB, при этом libmdbx сохраняет все ключевые возможности своего прародителя, такие как ACID и неблокирующее чтение с линейным масштабированием по ядрам CPU, а также добавляет несколько новых.

Описание отличий и усовершенствований libmdbx относительно LMDB заслуживает отдельной статьи (планируется публикации на «Хабре» и «Medium»). Здесь же уместно упомянуть самые важные и заметные:

  • принципиально больше внимания уделяется качеству кода, тестированию и автоматическим проверкам.
  • существенно больше контроля во время работы, начиная от проверки параметров, и до внутреннего аудита структур базы данных.
  • авто-компактификация и автоматическое управление размером БД.
  • единый формат БД для 32-битных и 64-битных сборок.
  • оценка объема выборок по диапазонам (range query estimation).
  • поддержка ключей вдвое большей длины и выбираемого пользователем размера страницы БД.

Выпущенный релиз-кандидат libmdbx является результатом решения (см далее) о разделении проектов MDBX и MithrilDB в августе 2019. При этом в libmdbx было решено устранить (рациональный) максимум технического долга и стабилизировать библиотеку. По-факту в обозначенном направлении сделано в 2-3 раза больше, чем оценивалось и планировалось исходно:

  • Реализована поддержка Mac OS и платформ «второго эшелона»: FreeBSD, Solaris, DragonFly BSD, OpenBSD, NetBSD. Поддержка AIX и HP -UX может быть добавлена при необходимости.
  • Проведена санация кода при помощи Undefined Behavior Sanitizer и Address Sanitizer, устранены все предупреждения при сборке с -Wpedantic, все предупреждения Coverity Static Analyzer и т. д.
  • Актуализация описания API.
  • Амальгамация исходного кода для удобства встраивания.
  • Поддержка CMake.
  • Поддержка вложенных транзакций.
  • Использование bootid для определения факта перезагрузки ОС (грязной остановки БД).
  • Сквозной подсчет обновлённых/старых страниц и расширенная информация о транзакциях.
  • Опция MDBX_ACCEDE для подключения к уже открытой БД в совместимом режиме.
  • Использование OFD-блокировок при их доступности.
  • Горячее резервное копирование в pipe.
  • Специализированный оптимизированный алгоритм внутренней сортировки (до 2-3 раз быстрее qsort() и до 30% быстрее std::sort()).
  • Увеличена максимальная длина ключа.
  • Автоматическое управление read ahead (стратегией кэширования файла БД в памяти).
  • Более агрессивная и быстрая авто-компактификация.
  • Более оптимальная стратегия слияния страниц B+ дерева.
  • Контроль не-локальных файловых систем (NFS, Samba и т.п.) для предотвращения повреждения БД при неверном использовании.
  • Расширен набор тестов.

Разработка «следующей» версии libmdbx будет продолжена в рамках отдельного проекта MithrilDB, в том время как вектор разработки «текущей» версии MDBX направлен на заморозку набора возможностей и стабилизацию. Такое решение принято по трём причинам:

  • Полная несовместимость: для реализации всех запланированных возможностей в MithrilDB требуется другой (несовместимый) формат файлов БД и другое (несовместимое) API.
  • Новый исходный код: для исходного кода MithrilDB обеспечена лицензионная независимость от LMDB, а сам проект планируется опубликовать под другой лицензией (одобренной OSI лицензией Apache 2.0, а не OpenLDAP Foundation).
  • Разделение позволяет избежать потенциальную путаницу, внести больше определенности и обеспечить независимость пути развития проектов.

MithrilDB как и MDBX, также основывается на дереве B+ и также будет отличатся предельно высокой производительностью, при этом устраняя ряд принципиальных недостатков MDBX и LMDB. В частности, будет ликвидирована проблема «долгих чтений», проявляющаяся как «распухание» БД из-за того, что переработка мусора блокируется долгим читающими транзакциями. Среди новых возможностей MithrilDB следует отметить:

  • поддержка размещения БД на нескольких разнородных носителях: HDD, SSD и энергонезависимой памяти.
  • оптимальные стратегии для «ценных» и «малоценных», для «горячих», «теплых» и «холодных» данных.
  • использование Merkle tree для контроля целостности БД.
  • опциональное использование WAL и существенно более высокая производительно в сценариях с интенсивной записью и гарантиями на целостность данных.
  • ленивая догоняющая фиксация данных на дисках.

Где-то можно глянуть какие накладные расходы при записи туда типовых логов (в пределах 0.5-2 дефолтного mtu) в условиях рамдиска для какого-то актуального референсного железа с 5-10к записей в секунду? Читай где посмотреть бенчмарки для магистральных кейсов на запись? Интересна разница в сравнении с аккуратной реализацией той же истории через mmap.

pon4ik ★★★★★ ()
Ответ на: комментарий от pon4ik

Где-то можно глянуть какие накладные расходы при записи туда типовых логов (в пределах 0.5-2 дефолтного mtu) в условиях рамдиска для какого-то актуального референсного железа с 5-10к записей в секунду? Читай где посмотреть бенчмарки для магистральных кейсов на запись? Интересна разница в сравнении с аккуратной реализацией той же истории через mmap.

Там внутри дерево B+, которое обновляется посредством copy-on-write. Соответственно, одно любое точечное обновление требует копирования/изменения листовой страницы и всех ссылающихся на неё страниц до корня дерева включительно, т.е. стоимость обновления равна высоте дерева, которая равна O(log(N)) от кол-ва записей. MDBX умеет обновлять страницы как непосредственно в памяти, так и через запись в файл (это определяется выбираемым режимом работы). Накладными расходами тут можно назвать захват мьютекса и копирование страниц перед их изменением. В свою очередь, это копирование позволяет параллельно и без блокировок читать только закоммиченные изменения.

Если «ту же историю» реализовать через mmap, то накладные расходы будут те же. Другое дело, что «через mmap» вы (скорее всего) сделаете что-то другое, и именно этим будет определяться разница. В простейшем случае, для логов будет достаточно кольцевого буфера или даже простой дозаписи в заранее созданный файл достаточного размера - тогда у вас как-бы нет накладных расходов. Но если вы станете двигаться в сторону ACID, то накладные расходы начнут появляться.

erthink ()

Использование bootid для определения факта перезагрузки ОС (грязной остановки БД).

Ясно, понятно. Тот самый гадальщик целостности данных по показаниям системного(?) времени.

anonymous ()
Ответ на: комментарий от erthink

Под той же историей я имел ввиду «запись логов». Но похоже это неудачное применение для этого инструмента, как минимум если интересует стабильность задержки.

pon4ik ★★★★★ ()

Мы активно применяем библиотеку в кросс платформенном проекте. Под linux все хорошо, но в windows, как я понимаю, нет возможности расширения занимаемого места и нужно преаллокациюия файла нужного размера. Проблема в том как угадать размер, а главное что делать, если бд заполнена. В этот момент по сути все останавливается и даже попытка удалить данные не срабатывает. Эта проблема как-то решается?

anonymous ()
Ответ на: комментарий от anonymous

Мы активно применяем библиотеку в кросс платформенном проекте. Под linux все хорошо, но в windows, как я понимаю, нет возможности расширения занимаемого места и нужно преаллокациюия файла нужного размера. Проблема в том как угадать размер, а главное что делать, если бд заполнена. В этот момент по сути все останавливается и даже попытка удалить данные не срабатывает. Эта проблема как-то решается?

Если я правильно вас понял, то вы спрашиваете про какую-то свою библиотеку, а не про libmdbx. Ибо в libmdbx такое расширение на ходу работает, достаточно задать параметры посредством mdbx_env_set_geometry(). Т.е. необходимо и достаточно задать нужные минимальный и максимальный размер, а также адекватные шаги приращения/уменьшения. Но вот менять верхний предел размера без необходимости не стоит, ибо для этого необходимо менять резервируемый размер адресного пространства, которое может быть занятым (особенно на 32-битных платформах).

В Windows нет официального метода изменять размер отображения, но есть неофициальный способ наращивать размер отображенной секции. Этот метод работает во всех версиях, подробности см исходный код функций mdbx_mmap() и mdbx_mresize(), в особенности вызов NtExtendSection().

Тем не менее, в Windows нельзя уменьшить размер отображения, в том числе уменьшить размер самого файла. Поэтому в libmdbx уменьшение производиться посредством полного unmap+map с приостановкой тредов на время ре-маппинга. Но и это не всегда помогает, так как уменьшить размер файла возможно только если нет других процессов, в которых он отображен в память в текущем размере.

erthink ()
Последнее исправление: erthink (всего исправлений: 1)
Ответ на: комментарий от anonymous

Спасибо за комментарий: очень полезно. Используем именно lmdbx. А это было во всех версиях?

Управление размером (включая функцию mdbx_env_set_geometry()) было реализовано в 2017, если не ошибаюсь.

Авто-компактификация в текущем виде (максимально агрессивно, но дешево по CPU) была добавлена прошедшей осенью.

erthink ()
Ответ на: комментарий от Adsky_Burunduk

опа, еще один ReOpenLDAP

За 17-19 годы из ReOpenLDAP в OpenLDAP они сами (OpenLDAP Foundation, Symas, Zimbra) неявно перетащили наверно пару десятков фиксов. Но именно неявно, как будто отсматривали историю моих коммитов или diff, пытались понять что и зачем было поправлено и затем делали похожие правки у себя.

Тем не менее, OpenLDAP скорее труп (не зря его выбросили из RHEL и собираются из SUSE). По той же причине я перестал портировать правки из OpenLDAP в ReOpenLDAP, не понятно кому это на самом деле надо (МегаФон перешел на использование Tarantool, что верно с инженерной точки зрения).

китаец-то на предмет патчей в свои творения совсем бесперспективен?

С Говардом даже обсуждать что-либо сложно. Он ревниво относится к любым «фишкам», если они замечены/придуманы не им, и еще более «упорото» отстаивает свои решения, даже если все вокруг указывают на недостатки. Если не ошибаюсь, он до сих пор стоит на позиции что LIFO-reclaiming невозможен и всё сломает (хотя этим решается одна из мега-проблем LMDB). Думаю аналогично будет и с авто-компактификацией и с range query estimation, хотя он вроде-бы еще не вникал. Поэтому переносить какие-либо «патчи» из libmdbx в MDBX примерно невозможно.

Но с MDBX/libmdbx ситуация другая. Это самостоятельный продукт, который превосходит LMDB по всем параметрам (других данных пока нет). Исходный код libmdbx изменился «совсем сильно», его просто в 2-3 раза больше. Как СУБД MDBX имеет больше возможностей и меньше проблем, другой формат БД и более развитое API. Проблема у MDBX по-сути одна - все уже знают и используют LMDB, очень похоже на ситуацию с Tarantool - он круче «редиски», но относительно мало известен.

erthink ()
Последнее исправление: erthink (всего исправлений: 1)
Ответ на: комментарий от Adsky_Burunduk

ладно фишки, а фиксы-то хотя бы?

Ну а что мне бегать за Говардом с призывами «дяденька возьмите фиксы»? Собственно какое-то время я так и делал, но безрезультатно и надоело.

Например, у Говарда нет полноценных тестов (по крайней мере в паблике), а внутри LMDB напрочь и давным-давно сломан внутренний аудит (само-контроль структуры БД по статистике использования страниц). При сборке компилятор выдает горы предупреждений, а Covery (и прочите статические анализаторы) Говард просто презирает. Аналогично с Valgrind, Address Sanitizer, UB-sanitizer и т.д. и т.п.

Если Говард не хочет наводить порядок, и устранять очевидные недоделки, то я не вижу смысла уговаривать принять его какие-то исправления.

С другой стороны, сейчас в LMDB где-то пяток багов, которым лет по 10. Если пользователи по-серьезному не попали на них за это время, то может они не так уж и критичны.

erthink ()
Последнее исправление: erthink (всего исправлений: 1)