Какие данные кэшируются и как работает кэширование
Что проверяют
Понимаете ли вы, где в Node.js-приложении живёт кэш и чем кэш внутри процесса отличается от внешнего. Следом обычно спрашивают, что будет с кэшем при нескольких инстансах и как не уронить базу, когда популярный ключ истёк.
Как отвечать
Кэшируют результаты запросов к базе, ответы внешних API, справочники и конфигурацию, отрендеренные страницы. Критерий один: данные читают часто, меняют редко, и небольшое устаревание допустимо.
Уровни кэша:
- в памяти процесса:
Mapили пакетlru-cacheс ограничениемmaxиttl. Быстро, но кэш у каждого процесса свой: приcluster, PM2 или нескольких подах копии расходятся, а при рестарте кэш пустеет. Живёт он в куче V8, и без лимита размера это утечка памяти; - внешний: Redis через
ioredisили официальныйredis, командаSET key value EX 60. Общий для всех инстансов, переживает деплой, но добавляет сетевой вызов и сериализацию.JSON.stringifyбольшого объекта выполняется синхронно и на время блокирует event loop; - HTTP: заголовки
Cache-Control,ETag(Express по умолчанию выставляет слабыйETag), кэш браузера и CDN.
Схема чаще всего cache-aside: смотрим в кэш, при промахе идём в базу и кладём результат с TTL. При изменении данных ключ удаляют. Для защиты от «стада» при промахе в Node есть простой приём: класть в Map не значение, а сам Promise запроса, тогда параллельные вызовы дождутся одного похода в базу.
Упомяните и встроенный кэш рантайма: модуль после первого require лежит в require.cache по полному пути, поэтому повторный импорт отдаёт тот же объект. У ES-модулей кэш тоже есть, но программно из него не удалить.
Где спотыкаются
Кэшируют в памяти без лимита размера, и процесс через несколько дней падает по памяти.
Не думают о нескольких инстансах и получают разные ответы на один и тот же запрос.
Кладут в общий кэш персональные данные под ключом без id пользователя, и один клиент видит профиль другого.