【问题标题】:Redis keys are not expiring - Laravel, PredisRedis 密钥不会过期 - Laravel、Predis
【发布时间】:2017-09-18 20:48:45
【问题描述】:

我正在使用Laravel 5.4Predis 和最新的Redis(或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 :)

【问题讨论】:

  • 真的没有意义,如果你请求一个key,过了过期时间,它会立即被删除。您确定在 60 秒过去之前没有设置密钥过期时间的语句吗?尝试TTL 获取密钥以检查它
  • 感谢 cmets @Mr.Phoenix。在得到答案的过程中,我确实最终使用了TTL

标签: php laravel redis predis


【解决方案1】:

对于使用 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。

【讨论】:

  • 这不能回答问题。问题在于如何处理密钥并使其过期的误解工作流程。它应该是对所选答案或我的答案的评论或建议。
【解决方案2】:

其他一些进程可能会调用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 时密钥不存在的情况。有关详细信息,请参阅文档。

【讨论】:

  • 很有道理。我现在知道 TTL 适合的地方。我会将它用作我的案例的伪代码,如果它有效......我认为它会......你的就是答案!
  • 感谢@for_stack,做到了。将感谢您的答案,并将发布我的案例的实际解决方案
  • 你如何在 laravel 中翻译这个,文档没有指定集合。 laravel.com/docs/5.7/redis
  • @MarkOdey 抱歉,我不熟悉 Laravel。请检查 user919426 的回答是否对您有帮助。
  • @for_stack 最后,laravel 文档提供了答案。它看起来像这样 Redis::set(''mykey", "1", 'EX', "3600")。基本上这个想法是参数只是从 redis 规范映射到 php。
【解决方案3】:

由于@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); 
}

完美运行!

【讨论】:

    【解决方案4】:

    如果你使用 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。

    【讨论】:

      猜你喜欢
      • 2012-08-04
      • 2017-02-12
      • 2020-09-26
      • 2020-04-19
      • 2016-04-25
      • 2016-05-14
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      相关资源
      最近更新 更多