Первая версия кэша блоков была классической: версия данных в имени ключа. Изменилось что-то в каталоге — подняли версию, ключи стали новыми, старые больше никто не читает. Просто и правильно. Пока не посмотришь, сколько места занимают «больше никто не читает».

Это вторая часть цикла «Кэш фрагментов и Redis».

Версии в ключе: инвалидация бесплатна, мусор — нет

$key = 'frag_grid_' . get_option('catalog_ver') . '_' . md5(serialize($args));

Сброс — это одна запись: catalog_ver++. Но все ячейки с прошлой версией остаются в базе сиротами до истечения срока. На каталоге с обменом 1С версия поднималась постоянно, и сирот набегало до 3 ГБ в сутки. Срок жизни держали коротким — 3 дня, — чтобы мусор хоть как-то уходил. А короткий срок означал, что редкие комбинации успевали истечь и отдавались с MISS.

И главное: после сброса каждая ячейка — MISS. Посетитель ждёт рендер, потому что под новым ключом ничего нет.

Версии в значении: stale-while-revalidate

Ключ стал стабильным — только параметры блока, хост и тип устройства. А версии переехали внутрь значения:

// что лежит в ячейке
[
    'html'  => '…',
    '_ver'  => 'v812',      // версия данных на момент рендера
    '_code' => 1760000000,  // версия кода: время изменения манифеста сборки
]

При чтении — три исхода:

УсловиеСтатусЧто происходит
_code не совпалMISSкод сменился, старая разметка может не работать с новым скриптом — рендер сейчас
_ver совпалHITотдать как есть
_ver не совпалSTALEотдать старое мгновенно, поставить горячую задачу на пересборку
function frag_get_or_render(string $type, array $args, callable $render): array {
    $key  = frag_key($type, $args);
    $cell = frag_store_get($key);
    if (!$cell || $cell['_code'] !== frag_code_version()) {
        $cell = frag_render_and_store($key, $type, $args, $render);   // MISS
        header('X-Frag-Cache: MISS');
    } elseif ($cell['_ver'] !== frag_data_version($type, $args)) {
        frag_queue_hot($type, $args);                                 // STALE
        header('X-Frag-Cache: STALE');
    } else {
        header('X-Frag-Cache: HIT');
    }
    return $cell;
}

Версии по разделам

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

Срок жизни — неделя

При чтении «отдай старое» длинный срок безопасен: устаревшее обновится при первом же показе. А короткий срок, наоборот, вредит — редкие комбинации успевают исчезнуть и отдаются с MISS. Срок вырос с 3 до 7 дней.

Цена решения

После изменения данных одну-две минуты показывается прежний контент — пока воркер не пересоберёт ячейку. Для каталога это допустимо; для цены в корзине — нет, и такие вещи в кэш блоков не кладутся.

Как проверить весь цикл

  1. первый запрос — MISS;
  2. второй — HIT;
  3. поднять версию раздела — следующий запрос STALE (~0,3 с) и горячая задача в очереди;
  4. воркер отработал — снова HIT с новым содержимым.

Кэш блоков есть, а после каждого обмена всё медленное?

Пришлите адрес — проверю, как у вас устроена инвалидация блоков.

· полезно?
АЧ
Алексей Чикун веб-разработчик, команда TRIOHEAD

Делаю сайты и сервисы целиком: от вёрстки до сервера. Пишу о том, что проверил на своих проектах.

Комментарии

// загружаю комментарии…

Комментарии публикуются после проверки. Ссылки и HTML не принимаются.