libfpta: в памяти, с персистентностью, быстрее хайпа
TRANSCRIPT
libfpta:– в памяти– с персистентностью– быстрее хайпа
Леонид ЮрьевAdvanced Research @ Positive Technologies
Алексей КопытовЭксперт @ Голос Разума
Потребовалосьоперативное хранилище
– очень быстрое
– для локальных процессов
– без излишеств, но развиваемое…
Взяли и сделали.
libfpta: Постановка задачиЛокально, DATA < RAM
– один нагруженный сервер– несколько читателей и 2-3 процесса-писателя
Быстро– если медленно, то не нужно
Долговечность иногда не важна– при аварии питания данные устаревают
Высокая готовность– минимальное время восстановления– падение не должно ломать или прятать данные
Позитивные таблицы1. Обзор
2. Варианты использования: Целевой и Неправильный
3. Плюсы
4. Минусы
5. Планы
6. Чем не устроили: Ignite, Tarantool, SQLite, RocksDB…
libfpta – Движок хранения
Компактная библиотека с лицензией LGPL
libfpta = libmdbx (key-value) + libfptu (tuples) + t1ha (hash)
Таблицы с «утиной» схемой, всяческие индексы
Экстремально быстрый, но без WAL (пока)
Похожий, но Иной
libfpta: 80% как у всех
1. Набор таблиц с колонкам и индексами
2. Машинные типы, дата-время, строки, NULL…
3. Курсоры
4. BREAD
5. Рой процессов
6. Пока отсутствуют: FOREIGN KEYs, JOINs
Внутри транзакцийчтения/записи
libfpta: ВнутриДанные отображены в RAM
– B+Tree, не LSM– ACID* поверх MVCC– MVCC посредством COW на уровне страниц
Key-value, кортежи, список таблиц, список колонок…– нет имен, только дайджесты t1ha
Предельно эффективно для машины– считаем кэш-линии и такты– ничего лишнего или неэффективного
libfpta: Не подойдет
Много «апдейтов» и– нельзя потерять при аварии питания– допустим простой при восстановлении= показан WAL
READ < WRITE && RAM < DATA= показан LSM
libfpta: ИдеальноТребуется предельная производительность
– ACID для локальной группы процессов– с выборкой диапазонов и курсорами
Не нужен WAL– требуется минимальное время простоя– допустимо потерять «хвост» при аварии( при kill -9 ничего не потеряется )– диск терпит WAF от апдейтов
READ > WRITE || RAM > DATA– иначе LSM даст больше
libfpta: СкоростьREAD / GET
𝑂 log(𝑁) = поиск в B+tree
Как std::map или чуть быстрее (за счет локальности)
На каждом CPUбез блокировок в БД
Подкачка если DATA > RAM
WRITE / UPSERT
𝑂 log(𝑁) = Изменение B+tree
Копирование страниц по высоте дерева
Транзакции строго последовательны
Фиксация на диске
MDBX
RocksDB
READ4threads SYNC LAZY
libfpta: Попугаи
MDBX
RocksDB
I/O SPACECPU
Производительность
Стоимость
libfpta: «Утиная» схема
Записи являются кортежами
Схема задает минимальный набор
Полей может быть больше…
Для «лишних» полей– машинный тип
– числовой тэг (до 1000)
– будет: справочник схемы
Дополнительныеполу-структурированные данные
libfpta: КортежиРеализованы в libfptu:
– похожи на BSON и MessagePack
– без сжатия
– поддерживаются коллекции (repeated в ProtoBuf)
– в заголовке есть «индекс»
– предельно удобны для машины
– подключаемый словарь схемы (будет, вместе с JSON)
– могут быть вложенным
– предусмотрены массивы
libfpta: Дубликаты
Дубликаты – это multi-value– во вложенных деревьях
– ключи не дублируются
– значения отсортированы
– курсоры могут ходить по «дубликатам»
– быстрый поиск и позиционирование
libfpta: КонкуренцияОдин писатель
– Один разделяемый мьютекс (1)– Изменения всегда последовательны
Много читателей– Подключение/отключение под вторым мьютексом (2)– Выполнение без блокировок внутри БД
Временно– Изменение схемы под мьютексом внутри процесса (3)
libfpta: ИндексыСоставные
– по совокупному значению колонок
Неупорядоченные– хэши t1ha вместо значений, требуют меньше места
Реверсивные– ключи сравниваются с конца, хорошо для доменов
Функциональные / Пользовательские (обдумываем)– как генераторы ключей, не компараторы– collate/uppercase
libfpta: Немного деталейПервичный индекс есть всегда
Нет RowID– есть последовательности– будет auto (эмуляция RowID)
Вторичные индекс через PK– как в MySQL, НЕ как в PostgreSQL– требуют уникальности PK
libfpta: Не как у людей…
Контроль уникальности– это атрибут индекса
NULL в индексах– заменяется на Designated NIL
– проверяется на уникальность
Триггеры– пока не хотим, нет «сервера»
Пока отсутствуют
– Collate и Case Insensitive
– FOREIGN KEYs
– JOINs
– OPTIMIZER / REWRITER
Пока не требовалось,но будет…
libfpta: Недостатки
Отсутствие WAL– требует смены формата
Проблема долгих чтений– требует большого рефакторинга
Наследство от LMDB
Были причины не трогать
Будем устранять
libfpta: WAL или NO-WAL?Без WAL
– Большой WAF
– Медленно на HDD
+ Моментальная готовность
Тем не менее+ OOM и kill = не проблема
+ есть LIFO для BBWC
Нам было достаточно,но WAL скоро будет
+ Небольшой WAF
+ Быстрее на HDD
± sync/flush (всё-таки нужен…)
– Replay после аварии
libfpta: Планы и хотелки
libmdbx (key-value):– Новое API
– Рефакторинг…
– Асинхронная фиксация
– Merkle Tree
– WAL
– Другая «сборка мусора»
– Вынос span-pages и поддержка RAW-устройств(Nexenta Edge)
libfptu (кортежи):– поддержка справочника схемы
– (де)сериализация в JSON
– (де)сериализация в MsgPack
libfpta (всё вместе):– поддержка python…
– «оптимизатор» запросов
– FK, JOIN, GIN…
libfpta: Трудности
KISS– взвешенный аскетизм, не переинженерить, меньше ребусов
Тесты– комбинаторная сложность
– оркестр процессов
– поведенческие паттерны
Люди– ищем в команду
Apache Ignite?
Java = неустранимые накладные расходы– не для предельной производительности
libfpta:1) Не нужна распределённость2) Не делает лишнего3) В несколько раз быстрее
Tarantool, Aerospike, etc…?
Сеть = неустранимые накладные расходы– системные вызовы, маршалинг, event loop
libfpta:1) Чтение линейно масштабируется по CPU2) Чтение без блокировок, непосредственно из RAM3) Интегрально в несколько раз быстрее*
SQLite, RocksDB…?
Одна БД = Один процесс
libfpta:1) Рой локальных процессов2) Два разделяемых мьютекса3) В несколько раз быстрее
Спасибо!Увидимся на «Хабре»
https://github.com/PositiveTechnologies/libfptahttps://github.com/PositiveTechnologies/libfptuhttps://github.com/leo-yuriev/libmdbx
libfpta