Is there good solution for cache tagging on PHP/Redis?
Asked Answered
F

3

6

I am looking for easy way to store cache in Redis and mark pieces of cache with tags, so when I needed I could easily delete all the cache marked with specific tag.

Is there a good ready to use solution for that? (I am going to use access Redis with PHP)

I would do it by myself, as I understand I need to store tags as sets, where values are keys of cache, that use the tag. I even can cover the situation when I delete cache and its key should be removed from tag's set (I can store list of tags in cached element for that). But I am not sure how to do it when cache expires, in this case its key will "stuck" in a tag and next time when I delete cache by tag - it will clean cache with key, where that key may not be used anymore.

So I am looking for ready solution, at least to see how it is done.

Faxon answered 26/10, 2015 at 23:27 Comment(1)
There's no problem with trying to delete a key after it was expired - the operation will fail but the end result is the same. Your approach to cache tagging is what's usually practiced.Akers
B
5

You can do this with Illuminate\Cache which is a part of Laravel although can be used on it's own.

In order to configure it you need to have the following composer libraries installed:

  • predis/predis
  • illuminate/redis
  • illuminate/cache

Here is an example:

<?php
require_once __DIR__ . '/vendor/autoload.php';

$servers = [
    'cluster' => false,
    'default' => [
        'host'     => '127.0.0.1',
        'port'     => 6379,
        'database' => 0,
    ],
];

$redis = new Illuminate\Redis\Database($servers);
$cache = new Illuminate\Cache\RedisStore($redis);

$cache->tags('posts', 'author_1')->put('post_1', 'Post 1 by Author 1', 1);
$cache->tags('posts', 'author_2')->put('post_2', 'Post 2 by Author 2', 1);
var_dump($cache->tags('posts', 'author_1')->get('post_1'));
var_dump($cache->tags('posts', 'author_2')->get('post_2'));
$cache->tags('author_2')->flush();
var_dump($cache->tags('posts', 'author_1')->get('post_1'));
var_dump($cache->tags('posts', 'author_2')->get('post_2'));

The result will be:

php test.php 
string(18) "Post 1 by Author 1"
string(18) "Post 2 by Author 2"
string(18) "Post 1 by Author 1"
NULL
Boehm answered 27/10, 2015 at 0:57 Comment(4)
That's looks interesting, thanks for the tip. Will try. Do you use it? How it handles related tags when cache expires (example i described in the question)Faxon
OK, I tried it and I didn't get it. As I understand - you set cache providing a list of tags and then you need to provide all those tags to get your cached data back. What is the point of it? I mean, why/how should I know all the tags that I provided creating cache when I need one?Faxon
How I see workflow should work: I have a list of tags when I create cache, like: Some page contains data from records user_1, user_2, article_10, image_120 so I create cache with key "page_50" and add all those tags. Now, when I need that cache - I just do $cache->get('page_50'). When user with id "2" changes his username I just call $cache->flushByTag('user_2') and all related cache (including "page_50") will be deleted.Faxon
I don't currently use this library, but none of the libraries I use support tagging (doctrine cache or phpfastcache). I tested getting values from the cache without specifying the tags again and it doesn't work. I looked into the code and when you put a value with tags it creates a special key that includes the sha1 of the tags. I think the idea is that you'll have an object that handles fetching items and that will be the only object that puts or gets those items from the cache so it will know which tags to use.Boehm
E
1

I would do it by myself, as I understand I need to store tags as sets, where values are keys of cache, that use the tag.

This will work if you will not limit memory avaiable for Redis (and usually there is hard limit for memory avaiable for cache). Because if Redis will remove set containing keys, and leave those keys you will not be able to delete them by tag.

Solutions:

  • make sure to have enough memory for cache
  • put sets in different Redis instance, which doesn't have limited memory
  • put sets in completely different place (like DB)
  • dont' use taging, use redis hashes http://redis.io/commands/hset to create namespaces (you can group your keys by one "tag").
Elevate answered 8/2, 2016 at 20:49 Comment(0)
S
0

Please note that you need version 4.2 of the Illuminate packages for this to work: Predis is not required.

"require": {
    "illuminate/redis": "^4.2",
    "illuminate/cache": "^4.2"
},
Sumerology answered 13/10, 2020 at 10:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.