Redis 密钥不会过期 - Laravel,Predis

Redis keys are not expiring - Laravel, Predis

我正在使用 Laravel 5.4, with Predis and the latest Redis (or Redis for Windows).

正在保存密钥,没有问题。所以,我怀疑这是配置问题。

问题是它们没有过期。 密钥在过期之前一直重复使用...类似于会话的工作方式。

如果密钥不存在,我会创建一次。按照同样的逻辑,我然后设置到期时间。

在控制器中,我有

use Illuminate\Support\Facades\Redis;

其中一个函数,获取连接实例

$redis = Redis::connection();

在我创建密钥之前,我检查是否存在(简化)然后创建并设置过期时间。

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); 
}

为什么它不能使密钥过期?

正如我提到的,其他一切正常。如果我监控,我看到密钥更新没有问题,并且可以查询它。

作为记录,我已阅读:

Laravel 文档中没有关于过期的内容:

更新 1

调查设置(更新)密钥重置到期的可能原因

更新 2

使用@for_thestack 的推理(在 REDIS 命令中)得出解决方案。使用代码查看我的答案。随时投票@for_thestack :)

其他一些进程可能会调用 SET 来更新键值对,在这种情况下,过期时间将被删除。

// 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

为了保持过期,更新键值对时,需要调用SET带过期参数。

// 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

您可以将这两个命令包装到一个 lua 脚本中,使其成为原子命令。并且你还需要处理调用TTL时key不存在的情况。详情见文档。

由于@for_stack 为我提供了逻辑(在 REDIS 命令和逻辑中),我接受了他的贡献作为答案。

我的问题是我不知道设置密钥,重置过期。所以让它工作,正如@for_stack所解释的那样,涉及:

  1. 如果密钥存在则获取 TTL
  2. 更新密钥后,将过期设置为我从 (1) 获得的 TTL

说明整体TTL不准确。从我在 (1) 中获得 TTL 值到我更新它的时间之间有几毫秒或微秒的间隔……这对我来说没问题!

所以对于我的 Laravel(PHP),Predis 场景,我执行以下操作:

在某些相关点,在代码的更高位置:

//get ttl - time left before expiry
$ttl = $redis->ttl($some_unique_key);

然后无论哪里我要更新值,我都在设置值后设置过期时间。 创建密钥的逻辑(在我的问题中)保持正确且未改变。

//***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); 
}

完美运行!

使用Laravel的可以使用EX param(expire resolution)+ttl。在下面的示例中,EX 表示 TTL 以秒为单位(请参阅 Redis 文档:https://redis.io/commands/set)。所以下面的结果将是存储在 $key 下的 $val 将在 35 秒后被删除。

Redis::set($key, $val, 'EX', 35);

在 predis 中你可以使用相同的,实际上 Laravel 在后台使用 predis。

如果您正在使用 Laravel 和 Redis Fassade,您也可以这样做

Redis::setex('yourkey', 120, 'your content'); // 120 seconds

而不是

Redis::set('yourkey', 'your content', 'EX', 120);

我不确定在 Laravel 5.4 中是否已经可行。 但肯定是 Laravel 8 和 Predis 1.1.