Replies: 2 comments 6 replies
-
This issue seems partially fixed in 10.0.0. Could you try it out with laravel 10 |
Beta Was this translation helpful? Give feedback.
-
I successfully extended Laravel's default cache driver to support tag expiration by creating custom TagSet. This implementation addresses a critical incident in a high-volume transaction application where the default behavior of Laravel’s cache tags, without automatic tag expiration, led to a production outage. The system encountered failures due to excessively growing cache tag keys, which necessitated implementing tag expiration to mitigate future risks. TaggedCacheProvider<?php
namespace App\Providers;
use App\Cache\RedisStore;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;
class TaggedCacheProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->app->booting(function () {
Cache::extend('redis', function (Application $app, $config) {
return Cache::repository(
new RedisStore(
$app['redis'],
$config['prefix'] ?? '',
$config['connection'] ?? null
)
);
});
});
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
// No additional boot logic required.
}
} RedisStore<?php
namespace App\Cache;
use Illuminate\Cache\RedisStore as BaseRedisStore;
use Illuminate\Cache\RedisTaggedCache;
use Illuminate\Contracts\Redis\Factory as Redis;
class RedisStore extends BaseRedisStore
{
public function __construct(Redis $redis, $prefix = '', $connection = 'default')
{
parent::__construct($redis, $prefix, $connection);
}
public function tags($names)
{
return new RedisTaggedCache(
$this,
new RedisTagSet($this, is_array($names) ? $names : func_get_args())
);
}
} RedisTagSet<?php
namespace App\Cache;
use Illuminate\Cache\RedisTagSet as BaseRedisTagSet;
class RedisTagSet extends BaseRedisTagSet
{
public function addEntry(string $key, ?int $ttl = 0, $updateWhen = null): void
{
parent::addEntry($key, $ttl, $updateWhen);
// Calculate tag TTL as original TTL plus 24 hours (86400 seconds).
$tagsTtl = $ttl + 86400;
foreach ($this->tagIds() as $tagKey) {
$this->store->connection()->expire(
$this->store->getPrefix() . $tagKey,
$tagsTtl
);
}
}
} ExplanationIn This approach enhances Laravel's caching capabilities, ensuring efficient management of tagged cache expiration. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
This seems like an oversight, but wanted to discuss it here before raising an issue regarding the illuminate/redis package...
illuminate/redis:9.52.0
Description:
Hello,
The
SET
keys created byilluminate/redis
grow indefinitely, never expire, and eat away at keyspace until a flush is needed.The graphs below show the past month where memory usage has remained the same, but the keys that can fit into memory continue to decline, because these "sets" within them continue to grow
We have eviction policy
allkeys-lfu
which means we are more likely to be left with these sets, than we are to be left with the cache they are meant to reference.We cache based on filter/sort query parameters present in the URL (sorted by key) as an example:
We have so many thousands of these as we have millions of users where cache relevant to any particular individual needs to be grouped with them.
A vast majority of the keys within this set however, have expired and don't even exist anymore, they will unfortunately stay there forever.
Steps To Reproduce:
FLUSHALL
orFLUSHDB
After waiting for the 1 second TTL to expire:
redis-cli
useKEYS *
redis-cli
useSCARD <the-standard-ref-key-you-found-in-the-above
// should see 10,000redis-cli
useMEMORY USAGE <the-same-key>
// should see the memory wasted to hold 10,000 expired keysQuestions
Beta Was this translation helpful? Give feedback.
All reactions