понедельник, 6 февраля 2012 г.

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


English post is here

Используется в одном из наших проектов такая штучка как Project Voldemort. Если вкратце, то это весьма любопытная реализация key-value storage aka NoSQL database. То есть даешь ему ключик и значение, и оно быстро в памяти это хранит/отдает и на диске тоже сохраняет, для персистентности. Оно на Java написано, и вообще больше из Java мира, но обслуживать и тюнить его приходится конечно нам, OPS Team. :)
В общем, столкнулись мы с одной проблемкой при эксплуатации, а именно - при большом трафике на этот Вольдеморт его база начала пухнуть со страшной силой - буквально десятки гигабайт в час - хотя девелоперы уверяли что такого количества данных там быть не должно. Пришлось копаться.
В результате "копаний" выяснилось следующее - в качестве бэкенда этот Вольдеморт использует так называемую 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 only   208,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 - средний размер ключа и данных, в байтах).
То есть, для наших данных, на каждый миллион записей нужно около 200 МБ кеша - а записей у нас был не один миллион. :(
Итого - после выставления адекватных кешей (bdb.cache.size), за сутки утилизация БД выросла с 7% до искомых 50%, соответсвенно размер БД упал В РАЗЫ.

Мораль - изучайте используемую технологию (даже если она используется не напрямую, а опосредовано. :) )

1 комментарий: