LINUX.ORG.RU

Кеш = метка времени + данные: как лучше хранить в Redis?

 


0

1

Задача: есть кешированный результат запроса (тяжёлый результат), есть метка времени его актуальности. Redis работает на одной машине вместе с приложением, соотв. «сетевые задержки» очень условны.

Нужно сначала вытащить метку времени, а потом по этой метке времени понять, требуется мне вытаскивать сами кешированные данные или нет.

Вопрос в том, как хранить метку времени и данные: хешем с полями ts и payload, двумя ключами вида object_id:ts и object_id:payload или вообще - метки времени в одной базе Redis, а кешированные данные в другой.

Мне было бы удобнее хранить как хеш, но поклонники Redis, насколько я знаю, хеши не любят и практически не используют. Поэтому я и думаю: раз не любят - есть за что? Например, не приведёт ли чтение только поля ts из хеша к тому, что в действительности «внутри себя» Redis считает всё значение целиком, потом десериализует из какого-нибудь MessagePack'а, после чего отдаст мне ts, параллельно закачав в ОЗУ ещё и весь payload?

Подход с замусориванием Redis составными ключами мне тоже кажется кривым: понятно, что это как минимум влияет на скорость работы поиска по заданному ключу: даже если там скорость поиска прямо равна O(N), всё равно в 2 раза больше ключей - пусть не в 2 раза, но всё-таки замедлит поиск.

Вопрос в том, есть ли какой-то «закешированный» best practice на этот совершенно типичный, на мой взгляд, случай? Безусловно, я могу полезть прямо в код Redis'а, почитать, как оно там устроено, но во-первых я не силён в сях, а во-вторых - если есть уже некий готовый, обоснованный подход, почему бы его не использовать (форумы для того и нужны, чтобы можно было делиться «пережёванными» результатами получения знаний).

В общем, «как лучше»?

Спасибо!

★★★★★

если кеш относительно долгий, может просто сделать так:

key = id + (now - now%cache_time)

С таким подходом можно делать фолбек на кешированное значение если апстрим не сможет обслужить запрос

В противном случае, что мешает делать

setex :object_id:, :payload:, :cache_lifetime:

собственно используя редис как кеш

anonymous ()
Ответ на: комментарий от anonymous

setex :object_id:, :payload:, :cache_lifetime:

Подошёл бы, но у меня сценарий совсем другой :)

У меня есть «реальные данные», после обновления которых в любом случае нужно апдейтить кеш, но у кеша нет лайфтайма.

DRVTiny ★★★★★ ()
Ответ на: комментарий от DRVTiny

тогда просто в блобе храни как поле date, всё равно же message pack есть

хеши нужны если ты хочешь перебить только часть значения, а тебе то всё равно данные обновлять вместе с таймстампом

а если не хочется править исходный payload, то можно просто вбить в виде list'а первым элементом ts, вторым payload. но я бы метку в блоб запихнул

читающий может по этому полю инициировать пересчёт значения?

anonymous ()
Ответ на: комментарий от anonymous

читающий может по этому полю инициировать пересчёт значения?

Именно! Это и делает читающий, если данные в кеше неактуальны в виду обновления исходных данных :)

DRVTiny ★★★★★ ()

Хеши не любят из за избыточности (одинаковые названия полей сохраняются для каждой записи в хеше) и часто вместо этого используют list. Например index 0 это всегда имя, index 1 - фамилия и тд.

параллельно закачав в ОЗУ ещё и весь payload

Он всегда там должен быть, redis не поддерживает virtual memory.
Вообще если тяжёлый запрос это запрос к другой RDBMS, то лучше в той БД все также и хранить, чтобы избежать проблем с десинхронизацией. Redis имеет смысл использовать только если есть большое кол-во DB writes, т.к на диск он их сразу не сохраняет.

bedman ()

В редисе же нативно можно задавать время жизни записи. Зачем лишний огород городить ?

Проверять при запросе - если данных нет. Значит протухли, либо небыло.

ovax ★★ ()
Ответ на: комментарий от ovax

Что ж такое-то: уже второй человек не читает и сразу отвечает :)

DRVTiny ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.