Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel - Erase all cache / redis keys that contain a specific string

Is it possible to erase all keys in redis using Laravel that match a specific string? For instance, if I wanted to forget keys that have the word products, it would forget the following keys:

laravel:896235872385237588327582370375acaca235325:products-list laravel:896235872385237588327582370375acaca235325:products-categories

I would run this on the redis server but I'm wondering if there's anything better that could be run via Laravel directly:

redis-cli keys "*" | grep "products" | xargs redis-cli DEL

like image 350
StackOverflowed Avatar asked Jan 28 '16 23:01

StackOverflowed


2 Answers

Why not:

public function forget($key_name)
{
    $redis = Cache::getRedis();
    $keys = $redis->keys("*$key_name*");
    $count = 0;
    foreach ($keys as $key) {
        $redis->del($key);
        $count++;
    }      
    return $count;  
}

And for production environment SCAN cursor [MATCH pattern] [COUNT count] should be used instead of "keys"

http://redis.io/commands/scan

Because you don't want to run out of memory in case you have tens of thousands keys in redis, and you don't want to block your whole redis instance by using "keys".

like image 133
my-nick Avatar answered Sep 30 '22 11:09

my-nick


This is the alternative by using scan instead of keys. Feel free to transform it to a recursive function if needed.

public function forgetWildcard(string $pattern, int $maxCountValue = 1000)
{
        $redis = Cache::getRedis();
        $currentCursor = '0';
        do {
            $response = $redis->scan($currentCursor, 'MATCH', $pattern, 'COUNT', $maxCountValue);
            $currentCursor = $response[0];
            $keys = $response[1];
            if (count($keys) > 0) {
                // remove all found keys
                $redis->del($keys);
            }
        } while ($currentCursor !== '0'); // finish if current Cursor is reaching '0'
}

Hint: to make it work for Laravel with prefixes I had to replace the pattern with the following: $this->getPrefix().'*:'.$pattern

like image 33
Tob0t Avatar answered Sep 30 '22 13:09

Tob0t