Redis 密钥不会过期 - Laravel、Predis

问题描述 投票:0回答:6

我正在使用 Laravel 5.4,以及 Predis 和最新的 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 :)

php laravel redis predis
6个回答
47
投票

对于使用 Laravel 的人来说,可以使用 EX param(过期解析)+ ttl。在下面的示例中,EX 表示 TTL 以秒为单位(请参阅 Redis 文档:https://redis.io/commands/set)。所以下面的结果将是存储在

$val
下的
$key
将在 35 秒后被删除。

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

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


7
投票

其他一些进程可能会调用

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 不存在的情况。详情请参阅文档。


7
投票

如果您正在使用 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。


6
投票

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

完美运行!


0
投票

这个方法对我有用

use Illuminate\Support\Facades\Redis;


Redis::rpush("REDIS_KEY", ['start' => microtime(true)]);

//get all redis data
$redisData = Redis::lrange("REDIS_KEY", 0, -1);
dd($redisData);

0
投票

例如:

这种方式不能设置过期时间:

Redis::set($lockKey, true, 'NX', 'EX', 30)

可以做到:

Redis::set($lockKey, true, 'EX', 30,  'NX')

说明:

set
方法中参数的顺序很重要。在 Redis 中,当您想要同时设置过期 (
EX
) 和条件(
NX
- 仅在键不存在时设置)时,
EX
选项必须位于
NX
之前。

Redis 命令语法要求将过期参数(

EX
PX
)放置在条件参数(
NX
XX
)之前。在第一个示例中,
NX
位于
EX
之前,这会导致命令解释不正确。

通过像第二个示例中那样切换

NX
EX
的顺序,Redis 可以正确处理这两个选项,仅当密钥尚不存在时才将密钥设置为 30 秒的过期时间。

© www.soinside.com 2019 - 2024. All rights reserved.