Кто с кешом работает, можно вопросик?

Gorynych

Посетитель PHP-Клуба
На самом деле у меня это одна из задач на собеседовании, но что-то захотелось озвучить )

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

$Cache = new Memcache;



$key = …;

$ttl = …15 минут…;

if (!($data = $Cache->get($key))) {

$data = … hard work …

$Cache->set($key, $data, …, $ttl);

}

Что произойдет на моменте, когда кэш по ключу some_key еще не установлен, или уже протух, и пришло 4-5 одновременных запросов к этому коду? Представьте (для простоты), что запросы идут друг за другом, пошагово. Если что-то в этой ситуации Вас не устраивает, как предлагаете улучшить код и почему?
 

AmdY

Пью пиво
Команда форума
Я про это писал в своём гавнобложике http://amdy.su/2021/08/23/cache/
Храни два экземпляра данных - один с ttl для, а второй без ttl чтобы брать данные пока генерится новый кэш.
 

Gorynych

Посетитель PHP-Клуба
Я про это писал в своём гавнобложике http://amdy.su/2021/08/23/cache/
Храни два экземпляра данных - один с ttl для, а второй без ttl чтобы брать данные пока генерится новый кэш.
угу, прочитал. Но - мои пять копеек:
- в целом тут более ключевое тут как раз про блокировку прежде чем ввалиться в работу. Но вариант has / set локов не айс. У memcache есть атомарный addб на редиске можно nxкидать
- такой хак был: не класть два значения, в класть ttl X 2 реальное время протухания дописывать в конец (соответственно накладные расходы - при чтении отделять такой хвост от данных)
- а вот смешное - если мы получили возможность поставить блокировку, не факт что это не произошло не в тот момент, когда другой запрос закончил считать данные,обновил кеш и отпустил блокировку. Т.е. напрашивается еще раз попробовать прочитать данные из кеша - вдруг они уже есть?
 
  • Like
Реакции: AmdY

MiksIr

miksir@home:~$
Нет ничего страшного, если ты пересчитаешь кеш два раза вместо одного. Страшно, когда ты пересчитаешь столько раз, что это сильно повлияет на время ответа базы. Сидеть же и ждать освобождения блокировки - это весьма опасное решение. Или отдавай протухшее, если не взял лок, или смотри в сторону раннего вероятностного пересчета.
 

AmdY

Пью пиво
Команда форума
Если несколько раз параллельно пересчитывать что-то тяжёлое, то батлнек организовывается даже при небольших нагрузках. Лучше отдать старое. Но с мире CRM иногда нужен лок, там нагрузки совсем небольшие обычно и актуальность данных важнее задержки в секунду.
 

MiksIr

miksir@home:~$
Задержка в секунду - это если все пошло как планировалось. Никакой процесс не упал, никто не забыл снять лок и тп. А значит еще городить логику форсированного снятия лока, раньше снимешь - вероятность параллельного запроса, позже снимешь - сам себе дос устроишь.
Если прям такой запрос, что два параллельных просаживают базу, то лучше всего внешний пересчет. Если допустим ранний пересчет - то вероятностный пересчет с неблокирующим локом для гарантии.
 

Gorynych

Посетитель PHP-Клуба
что-то ощущение недопонятости остается
вы с горизонтальным масштабированием и тяжелыми пересчетами сталкиваетесь?
кроме задержек в секунду есть и помягче, например:
Код:
[
public function setWaitLock($key, $wait = 50/*millisec*/, $tries = false)
{
    if(!$tries) $tries = 10;
    if($wait < $tries) {
        $tries = $wait;
        $wait_per_try = 1;
    } else {
         $wait_per_try = ceil(1000*$wait/$tries);
    }

    while($tries-- > 0) {
        if($this->link->set("lock::".$key, 1, ['nx', 'px' => $wait])) return true;
        if ( $tries ) usleep($wait_per_try);
    }
    return false;
}
код под редисочку, если что
 
Последнее редактирование:

Gorynych

Посетитель PHP-Клуба
я могу еще про сервисы и асинхронные ответы в ту же тему задвинуть, когда вы в сервис постучали, nginx в пыхочку запрос отдал, сам моргнул (и никакого тебе 200 ок), а пыхочка отработала и обратно вернула ответ пакет обработан. Но ощущение пока что как-то плохо получается пояснить проблемы.
 

fixxxer

К.О.
Партнер клуба
Оба разумных варианта уже озвучены:
1. отдавать старое
2. лочить на время обработки

Первый, конечно, не всегда возможен: одно дело старый комментарий в бложике не появится, другое дело списание с баланса не учтется.

С атомарными операциями в memcached и redis уж разберитесь, про это написаны миллионы страниц уже :)

Храни два экземпляра данных - один с ttl для, а второй без ttl чтобы брать данные пока генерится новый кэш.
Как расточительно :) Можно просто хранить свой "мягкий" ttl рядом с данными.
 

MiksIr

miksir@home:~$
> другое дело списание с баланса не учтется
ну для такого случая ttl тоже не поможет, тут исключительно пуш обновление кеша или же пулл, но с отдельным запросом форсирующим пересчет, как это делают в банках
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
1. это на какую позицию собеседование с таким вопросом?
я могу сходу перечислить десяток разных вариантов решения в зависимости от инфраструктуры, архитектуры, бюджета, NFR,
однако, по такой задаче не может существовать какого-то общего решения без учета железа и сети
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
это на какую позицию собеседование с таким вопросом? я могу сходу перечислить десяток разных вариантов решения в зависимости от инфраструктуры, архитектуры, бюджета, NFR, и ни одного общего решения
Ну так такие вопросы как раз помогают определить уровень кандидата.
Впрочем, как и кандидату определить уровень собеседующего - по реакции на ответ. ;)
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
2. неужели никто не изучал как 40 лет назад спроектировали DNS? это лучшая архитектура кеширования на уровнях от корневых зон до service discovery в контейнеров
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Впрочем, как и кандидату определить уровень собеседующего - по реакции на ответ. ;)
ага, года два назад какой-то эстонский стартап в сфере трейдинга мне предложил написать ТЗ за пару часов - реально работающий биллинг платежей, я напомнил, что работал в системном банке и попросил уточнить NFR ... и ушли в направлении, которым идет 97% стартапов мира
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Ну так такие вопросы как раз помогают определить уровень кандидата.
бизнесу нужен сотрудник на задачи, а вопросы уровня докладов на конференциях - сжигание денег на развлечение HR-ов и собеседующих

иногда я в подобных ситуациях прошу уточнить, в течение скольких часов я могу отвечать на вопрос 😁

ТС мои комменты не помогут, но позволят хотя бы оценить собеседующих, которые, вероятно, просто развлекаются
 
Последнее редактирование:

Gorynych

Посетитель PHP-Клуба
1. это на какую позицию собеседование с таким вопросом?
я могу сходу перечислить десяток разных вариантов решения в зависимости от инфраструктуры, архитектуры, бюджета, NFR,
однако, по такой задаче не может существовать какого-то общего решения без учета железа и сети
эх.. сейчас тогда уйдем в вечный дискурс про а у кого какие грейды по уровням? Ладно, если про мой вопрос, то честно напишу что это это на уровень с претензией на ведущего. Обычно очень помогает понять как кандидат может думать.
 

Gorynych

Посетитель PHP-Клуба
Вы собеседуете на ведущего? "пыхочка" и "редисочка"?
"пыхочка" и "редисочка" - это чем-то оскорбительно для а) кандидата или б) технологий? Мне кажется технологии это переживут.

Лично для меня гораздо хуже, если кандидат не сможет объяснить отличия 7.4 от других семерок, или 7.х от 5.6. Или не интересуется чем Redis отличается от Memcache, или вдруг думает, что сетевая связанность и объем трафика между хранилищами и приложением проблема исключительно для админов.
 
Сверху