I am using Laravel 5.4 , with Predis and the latest Redis (or Redis for Windows ).
The keys are being saved without issue. So, I doubt it's a configuration issue.
The problem is that they are not expiring. The key is reused until it expires...similar to how a session works.
I create the key once, if it does not exist. In that same logic I then set the expiration time.
In the Controller, I have
use Illuminate\Support\Facades\Redis;
In one of the functions, Get the connection instance :
$redis = Redis::connection();
Before I create the key, I check the existence (simplified) then create and set expiration.
if(!$redis->exists($some_unique_key))
{
//set the key
$redis->set($some_unique_key, 'Some Value'));
//set the expiration
//I understand this means expire in 60s.
$redis->expire($some_unique_key,60);
}
Why could it not be expiring the key?
As I mentioned, everything else works. I see the key updating without issue if I monitor, and can query it.
For the record, I have read:
There is nothing on expiration on the Laravel documentation:
UPDATE 1
Investigating a possible cause where setting(updating) the key resets the expiry
UPDATE 2
Used @for_thestack's reasoning (in REDIS commands) to come up with the solution. See my answer with the code. Feel free to upvote @for_thestack :)
For those who uses Laravel, it is possible to use EX param (expire resolution) + ttl. In below example EX means that TTL is expressed in seconds (see Redis docs: https://redis.io/commands/set ). So the result of below will be that $val
stored under $key
will be removed after 35 seconds.
Redis::set($key, $val, 'EX', 35);
In predis u can use the same, actually Laravel uses predis under the hood.
Some other process might call SET
to update the key-value pair, in this case, the expiration will be removed.
// set expiration
EXPIRE key expiration_in_seconds
// update key-value pair with no expiration
SET key new_value
// now, expiration has been reset, and the key won't be expired any more
In order to keep the expiration, when you update the key-value pair, you should call SET
with expiration parameters.
// get TTL, i.e. how much time left before the key will be expired
TTL key
// update with expiration parameter
SET key new_value EX ttl
You can wrap the two commands into a lua script to make it atomic. And you also need to take care of the case that key doesn't exist when you call TTL
. See the document for details.
Since @for_stack provided me with the logic(in REDIS commands & logic), I accepted his contribution as the answer.
My problem was that I did not know that set ing the key, resets the expiry. So making it work, as explained by @for_stack involves:
It means that the overall TTL is not precise. There is a margin of milli or micro seconds that it takes between the time I got the TTL value in (1) to the time I update it.... which is fine by me!
So for my Laravel(PHP), Predis scenario, I do the following:
At some relevant point, higher up in the code:
//get ttl - time left before expiry
$ttl = $redis->ttl($some_unique_key);
Then wherever I have to update the value, I set the expiry after setting the value. The logic for creating the key(in my question) remains correct and unchanged.
//***note that I am UPDATING a key. Checking if it exists then I update
if($redis->exists($some_unique_key))
{
//set/up the key
$redis->set($some_unique_key, 'Some New, Updated, Value'));
//Do some work
//set the expiration with the TTL value from (1)
$redis->expire($some_unique_key,$ttl);
}
Works perfectly!
If you're using Laravel and the Redis Fassade, you can also do
Redis::setex('yourkey', 120, 'your content'); // 120 seconds
instead of
Redis::set('yourkey', 'your content', 'EX', 120);
I'm not sure if it was already possible in Laravel 5.4. But definitely with Laravel 8 and Predis 1.1.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.