NoSQL / Подводные камни в Project Voldemort

в 13:27, , рубрики: java, tuning, voldemort, метки: , ,

Используется в одном из наших проектов такая штучка как Project Voldemort.
Если вкратце, то это весьма любопытная реализация key-value storage aka NoSQL database, реализованная в недрах Linkedin. То есть даешь ему ключик и значение, и оно быстро в памяти это хранит/отдает и на диске тоже сохраняет. Интересна она, в принципе, не этим, а своей реализацией кластеризации, неплохой скоростью, ну тем что часто используется в проектах на Java. В принципе, подробного обзора этой БД на Хабре не было, и можно как нибудь сделать. Но рассказать я тут хочу пока о одних граблях, с которыми пришлось столкнуться.
А столкнулись мы с одной проблемкой при эксплуатации, а именно — при большом трафике на Вольдеморт его база начала пухнуть со страшной силой — буквально десятки гигабайт в час — хотя девелоперы уверяли что такого количества данных там быть не должно. Пришлось копаться.
В результате «копаний» выяснилось следующее — в качестве бэкенда Voldemort по умолчанию использует так называемую BDB JE — Berkeley DB Java Edition, и оказалось что этот JE совсем не похож на обычную Berkeley DB. Оказалось, что она write only — то есть, основана на том же принципе что и журнализируемые ФС — при любой операции — запись, обновление, удаление — данные ДОЗАПИСЫВАЮТСЯ в файлики на диске и сами по себе они НЕ УДАЛЯЮТСЯ. Специальный cleaner процесс потом ходит и чистит устаревшие данные — проверяет общую утилизацию файлов в БД, и если она меньше bdb.cleaner.minUtilization процентов (по дефолту — 50%) начинает проверять каждый файлик, и если в нем меньше bdb.cleaner.min.file.utilization процентов (5% по дефолту) файлик удаляется, и данные из него переносятся в новый файл.
Хорошо. Вроде бы надо поиграться этими параметрами, но что то не похоже чтобы утилизация у нас была 50% — уж очень много данных на диске хранится.
Проверяем — # java -jar /usr/local/voldemort/lib/je-4.0.92.jar DbSpace -h /usr/local/voldemort/data/bdb -u
File Size (KB) % Used
-------- --------- ------
00000000 61439 78
00000001 61439 75
00000002 61439 73
00000003 61439 74
...
000013f6 61415 1
000013fd 61392 2
000013fe 61411 3
00001400 61432 2
00001401 61439 1
...
0000186e 61413 100
0000186f 61376 100
00001870 16875 95
TOTALS 112583251 7
Опа-па. Не работает значит чистка. Пытаемся увеличить количество потоков для чистки — играемся с bdb.cleaner.threads (по умолчанию 1) — без пользы. В результате гугления натыкаемся на тред в форуме, посвященном BDB JE (как выяснилось, очень полезный форум, если вы в каком либо виде используете BDB JE — обязательно почитайте).
Тред (к сожалению, сейчас что то найти его не могу) ясно говорит о том, что на очистку может сильно влиять размер кеша BDB. То есть, если кеш маловат — чистка может даже не запускаться, так как при большом количестве ключей желательно чтобы все они влезали в кеш, иначе сильно падает производительность очистки. Желательный размер кеша можно прикинуть используя следующую команду —# java -jar /usr/local/voldemort/lib/je-4.0.92.jar DbCacheSize -records 1000000 -key 100 -data 300
Inputs: records=1000000 keySize=100 dataSize=300 nodeMax=128 density=80% overhead=10%
Cache Size Btree Size Description
-------------- -------------- -----------
177,752,177 159,976,960 Minimum, internal nodes only208,665,600 187,799,040 Maximum, internal nodes only
586,641,066 527,976,960 Minimum, internal nodes and leaf nodes
617,554,488 555,799,040 Maximum, internal nodes and leaf nodes
Btree levels: 3
(где key и data — средний размер ключа и данных, в байтах, records — количество записей).
То есть, для наших данных, на каждый миллион записей нужно около 200 МБ кеша — а записей у нас был не один миллион. :(
Итого — после выставления адекватных кешей (bdb.cache.size), за сутки утилизация БД выросла с 7% до искомых 50%, соответсвенно размер БД упал В РАЗЫ.
Мораль — изучайте используемую технологию, даже если она используется не напрямую, а опосредовано.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js