awesome-everything EN
↑ Обратно к восхождению

Кеширование

Кэширование, капстоун: чтение кода и заголовков

Суть Читай реальные заголовки, хэндлеры и single-flight lock поперёк стека кэширования, предсказывай поведение и выбирай исправление с наибольшим рычагом.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min

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

Цель

Отработай цикл, который ты запускаешь на каждом инциденте кэширования: прочитай директиву или код на горячем пути, предскажи, где каждый уровень кэширует или утекает, и возьмись за изменение, чинящее композицию — а не более громкий TTL.

Сниппет 1 — заголовок Cache-Control

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=600

Это публичное API прайс-листа, которое команда хочет кэшировать на edge CDN, часто обновлять и всё равно отдавать, если origin ляжет.

Викторина

Что этот заголовок реально делает против того, что хочет команда, и какое исправление с наибольшим рычагом?

Сниппет 2 — хэндлер условного GET

app.get("/articles/:id", async (req, res) => {
  const article = await db.getArticle(req.params.id);
  const etag = `"${article.version}"`;
  res.setHeader("ETag", etag);
  res.setHeader("Cache-Control", "private, max-age=0, must-revalidate");
  // всегда шлёт полное тело
  res.json(article);
});
Викторина

Хэндлер ставит ETag, но оптимизация условного запроса никогда не срабатывает. Чего не хватает и в чём выигрыш после исправления?

Сниппет 3 — stampede lock

async function getHot(key) {
  let val = await cache.get(key);
  if (val !== null) return val;

  // холодно: каждый параллельный вызывающий доходит сюда и пересчитывает
  val = await expensiveQuery(key);   // бьёт в БД
  await cache.set(key, val, { ttl: 60 });
  return val;
}
Викторина

Горячий ключ истёк, и 5000 запросов приходят в одну секунду. Что происходит и в чём single-flight исправление?

Сниппет 4 — тайминги SWR

Cache-Control: public, s-maxage=60, stale-while-revalidate=300

Ответ закэширован в 12:00:00. Запросы приходят в 12:00:30, 12:01:30 и 12:07:00. Записи или purge не было.

Викторина

Что разделяемый кэш отдаёт в каждый из трёх моментов?

Итог

Читай сверху вниз: заголовок Cache-Control должен разделять edge и браузер (s-maxage против max-age) и нести SWR плюс stale-if-error, чтобы обновляться мягко и пережить сбой; ETag инертен, пока сервер не читает If-None-Match и не отвечает 304; холодный горячий ключ требует single-flight, чтобы 5000 промахов стали одним запросом к БД; а два окна SWR решают, получит ли читатель свежее попадание, мгновенно-устаревшее-с-фоновым-обновлением или блокирующую ревалидацию. Диагностируй по заголовку и логу, чини композицию, затем перепроверь под той же нагрузкой.

Продолжить восхождение ↑Кэширование, капстоун: спроектируй многоуровневую стратегию
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.