All streams
Search
Write a publication
Pull to refresh
96
0
Олег Герасимов @olegator99

Пользователь

Send message

Rocksdb функционально ближе к Leveldb, от которой она и произошла. Добавить к ней функционал выборок по N произвольным индексам, Join и произвольные сортировки — задача возможно даже сложнее, чем написать с нуля, т.к. Архитектурно RocksDB это все же продвинутая дисковая K-V


Смотрел на нее, как на дисковый backend вместо leveldb, но большого профита по отношению к leveldb в этом разрезе не нашел.

В рамках этих тестов — не сравнивали, но раньше сталкивались.
Несколько месяцев назад проводился Mailru Highload Сup. https://highloadcup.ru/rating/. Пользуясь случаем, кстати, огромное спасибо организаторам :)


Решение но основе Reindexer/C++ прошло в финал, а решение на основе Tarantool+lua — нет.

Каждый тест 10раз x 5 секунд.
Объем данных 100К записей x 0.5кб. Увеличение объема в 10 раз существенно результаты не меняло, однако со всеми запущенными базами контейнер переставал помещаться в память, что сильно усложняло тесты.

В планах — встроенный Web интерфейс для просмотра и редактирования данных в БД, а так же консольная утилиты для дампа/рестора БД.
Еще в обозримых планах бинарный протокол для сервера и коннекторы к другим ЯП.


Из функционала движка задумываемся об R-Tree, оптимизация операция записи, и еще некоторый ряд оптимизаций.


Начинал сам, а сейчас уже разработка коллективная — в проекте участвует несколько человек.

Отчего же, не указали. Еще как указали:


Сейчас доступно три варианта подключения Reindexer-а к проекту:
библиотекой к Golang
библиотекой к C++
standalone server, работающий по http протоколу

Конечно, сеть скорости не прибавляет. Но и подключение либой — не серебряная пуля.
К примеру, sqlite, подключается либой, без сети, однако цифры у нее — так себе.


Сеть заметно накидывает на Latency. Примерно ~30мкс на запрос, это правда. Но Latency мы в этой статье не сравниваем.


А на RPS, которые мы сравниваем — влияние не так велико. Точные цифры сказать сложно, но по ощущениям на Get By ID ~20%-30%, на остальных более тяжелых запросах — способ подключения базы влияет еще меньше.

По отказо-устойчивости хранилища Reindexer зависит от storage backend-а, сейчас это leveldb со всеми ее плюсами и минусами. Если окажется, что leveldb не устраивает, легко можно перейти на любой другой. Но пока устраивает.


Сами данные хранятся с минимальными накладными расходами (+~32 байта на одну запись)


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


Если говорить в среднем, то потребление ОЗУ получается 2-3х от размера исходных данных (но зависит от большого количества факторов)

Специально проверил. В данном случае корректно:


Если говорить о c <-> cgo, то вот цифры с прод сервера:


root@90b6ed8da107:/build/tst# go test -bench .  -benchmem
goos: linux
goarch: amd64
BenchmarkCGO-24     20000000           109 ns/op           0 B/op          0 allocs/op

Если про остальные тесты, выборочно запустил несколько бенчмарков на prod сервере. Соотношение результатов ± аналогичное.

Согласен, приведение interface{} не очень затратная операция.
Однако, каждое приведение interface{} к конкретному типу, это как минимум лишнее ветвление, и дополнительные затраты по памяти на хранение информации о типе каждой переменной. Когда данных много, и индекс активно используется — даже незначительный оверхед на приведении типа заметно ударит по производительности.

Из Java проекта пока можно только по http подключиться, но с ним будет конечно, большой overhead. В не очень далеких планах есть реализация бинарного протокола, тогда и можно будет сделать хороший коннектор для Java


А эти графики с пылу-жару — для хабра сделали, еще не успели оформить и выложить в документации git проекта.

Мы рассматривали тарантул как один из вариантов, но он не подошел функционально. Как минимум, хватало индексов по полям массивам и полнотекстового поиска.


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

Reindexer сразу после запуска считывает весь кэш с диска в память. Скорость загрузки мы специально не измеряли, но в среднем, база в ~800MB считывается в память где то за 5-7 секунд.
То есть, в нашем случае, через 7 секунд после запуска получаем полностью прогретый кэш.

Да уж!


У полнотекстового поиска морфология реализована на уровне поиска по корням слов и возможных опечаток. Например, если в документе есть слово "задачами", то документ найдется по запросам "задача", "зодачей" и даже "zadacha". Это в быстром движке. В продвинутом -триграммы, он допускает еще больший разброс словоформ.


Аггрегация тоже есть — вот описание


Свойства массивы — есть. Они нам потребовались в бизнеслогике с самого начала, и кстати сильно ограничили набор готовых решений, которые мы рассматривали.

Если честно, то пока руки не дошли. Да и Ignite в golang очень скудно представлен — нагуглиась только одна либа https://github.com/amsokol/go-ignite-client

Пробовали разное. Если мне не изменяет память, варьировали количество шард, использовали наиболее подходящие mappings. Делали разнообразные sysctl, увеличивали до беспредела размер памяти под JVM...

Я ждал этого вопроса. Наверно стоит начать с того, что переключение между go и c++ действительно не бесплатно, но весьма легковесно. Например, у меня на ноутбуке это порядка 100нс. Это время сопоставимо со временем обращения к map, и на остальном фоне практически не заметно — возможно, что-то в районе <1% от общей загрузки.
В Reindexer количество переключений go — с минимально: 1-ин раз на Query.Exec(), 2-рой раз на iterator.Close().


Решение на C++ выбрано сознательно по двум основным причинам:


  • Для эффективной реализации индексов активно используются "generics", которых в golang, увы нет. В golang для этого пришлось бы либо существенно раздувать кодовую базу, копипастой реализаций индексов под каждый тип, либо использовать рантайм interface{}, который бы существенно ударил по производительности.
  • В golang есть GC. Если данные хранить в Go (например 5м записей, в каждой из которых есть по 10 строчек), это как минимум 50М объектов на куче. Расплатой за это станут заметные паузы на GC, и как следствие общее замедление работы. В C++ нет GC, и как следствие проблемы с GC нет, как класс.

Обычный дисковый. Похоже, у MongoDB In-memory движок есть только в Enterprise редакции, поэтому сходу его опробовать не удалось.
Так же, в комментарии выше написал результаты тестов с базой в tmpfs. Результаты принципиально не изменились.

Согласен.
Прогнал тесты mysql с in-memory mysql (ENGINE=MEMORY) — пришлось оторвать полнотекстовый поиск, т.к. ENGINE=MEMORY его не умеет. Результаты такие:
mysql byid -> 12917.17
mysql 1cond -> 10845.16
mysql 2cond -> 10114.12
mysql update -> 8447.82 (вырос в 10 раз, скорее всего, за счет отказа от полнотекстового индекса)


Судя по всему, mongo умеет in-memory только в enterprise редакции. Поэтому удалось проверить только на tmpfs:
mongo byid -> 12808.25
mongo 1cond -> 11279.45
mongo 2cond -> 7895.26
mongo text -> 7258.60
mongo update -> 809.77


Итого, выигрыш получился не принципиальный...

Вот жеж! А ведь поправил еще вчера, но почему то картинка не обновилась, похоже где то в кэше осела старая. Поменял имя файла, теперь точно должно быть ок.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Works in
Date of birth
Registered
Activity