Комментарии 7
Cамый неприятный случай у меня был на такой задаче:
На сервере лежат файлы, содержащие записи переменной длины, размеры файлов могут достигать десятков Гб.
Клиент запрашивает выборку записей из заданного диапазона, размер выборки колеблется от нескольких байт то сотен Мб. Одна и та же выборка может запрашиваться многократно, есть жесткие требования на скорость отдачи (почему здесь собственно и оказались файлы, а не СУБД).
Сначала попытались сделать что-то типа кэширования: закачивать в память выборку целиком (в Buffer), отдавать клиенту, но из памяти не удалять, чтобы повторные запросы к той же выборке были быстрыми. Думали, раз кэш самодельный, под особенности запросов мы всегда сможем его докрутить. Как бы не так :)
Все было неплохо, пока несколько сотен клиентов не начали запрашивать одновременно разные выборки по паре сотен Мб. В этот момент память стремительно заканчивается даже с полностью очищенным кэшем.
Проблему решили так: вместо буферов в кэше стали держать указатели на start/end-позиции в файле (на самом деле там было чуть хитрее, ибо даже указатели при неудачном стечении обстоятельств в оперативную память не помещаются), а по запросу клиента делать что-то вроде fs.createReadStream(...).pipe(...).
В результате система начала летать, потребление памяти нодой не выходит за 200Мб под максимальной нагрузкой (~500 клиентов, которые шлют запросы без пауз — вот такие злые клиенты :)).
Плюс еще один полезный эффект: в ядре ОС есть свой буфер и по факту повторные запросы к одной и той же выборке из файла за относительно короткий промежуток времени ОС выполняет без обращения к диску. Т.е. на самом деле наши попытки кэширования фрагментов файлов в основном ничего не ускоряли, а только увеличивали расход оперативки.
А еще из-за этой задачи перешли с ноды 6 на 8, т.к. по тестам под нагрузкой восьмерка показала существенно меньший расход памяти, а некоторые критичные в данной задаче вычисления стали выполняться быстрее. Но другие проекты переводить на 8 не тороплюсь, пока страшно… :)
На сервере лежат файлы, содержащие записи переменной длины, размеры файлов могут достигать десятков Гб.
Клиент запрашивает выборку записей из заданного диапазона, размер выборки колеблется от нескольких байт то сотен Мб. Одна и та же выборка может запрашиваться многократно, есть жесткие требования на скорость отдачи (почему здесь собственно и оказались файлы, а не СУБД).
Сначала попытались сделать что-то типа кэширования: закачивать в память выборку целиком (в Buffer), отдавать клиенту, но из памяти не удалять, чтобы повторные запросы к той же выборке были быстрыми. Думали, раз кэш самодельный, под особенности запросов мы всегда сможем его докрутить. Как бы не так :)
Все было неплохо, пока несколько сотен клиентов не начали запрашивать одновременно разные выборки по паре сотен Мб. В этот момент память стремительно заканчивается даже с полностью очищенным кэшем.
Проблему решили так: вместо буферов в кэше стали держать указатели на start/end-позиции в файле (на самом деле там было чуть хитрее, ибо даже указатели при неудачном стечении обстоятельств в оперативную память не помещаются), а по запросу клиента делать что-то вроде fs.createReadStream(...).pipe(...).
В результате система начала летать, потребление памяти нодой не выходит за 200Мб под максимальной нагрузкой (~500 клиентов, которые шлют запросы без пауз — вот такие злые клиенты :)).
Плюс еще один полезный эффект: в ядре ОС есть свой буфер и по факту повторные запросы к одной и той же выборке из файла за относительно короткий промежуток времени ОС выполняет без обращения к диску. Т.е. на самом деле наши попытки кэширования фрагментов файлов в основном ничего не ускоряли, а только увеличивали расход оперативки.
А еще из-за этой задачи перешли с ноды 6 на 8, т.к. по тестам под нагрузкой восьмерка показала существенно меньший расход памяти, а некоторые критичные в данной задаче вычисления стали выполняться быстрее. Но другие проекты переводить на 8 не тороплюсь, пока страшно… :)
Круто, Вы отказались от СУБД и написали свою со своими индексами =)
Ну, я же написал, почему СУБД не использовались. Да, что-то похожее по смыслу на СУБД-индексы мы действительно написали, эти индексы получились очень простыми, т.к. файлы после заливки в систему не меняются, а поиск нужен исключительно по диапазону номеров записей. Вас что-то смущает в таком подходе?
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Решение проблем неправильного использования памяти в Node.js