我正在使用 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 :)
对于使用 Laravel 的人来说,可以使用 EX param(过期解析)+ ttl。在下面的示例中,EX 表示 TTL 以秒为单位(请参阅 Redis 文档:https://redis.io/commands/set)。所以下面的结果将是存储在
$val
下的 $key
将在 35 秒后被删除。
Redis::set($key, $val, 'EX', 35);
在 predis 中你可以使用相同的,实际上 Laravel 在底层使用 predis。
其他一些进程可能会调用
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 不存在的情况。详情请参阅文档。
如果您正在使用 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。
由于@for_stack 为我提供了逻辑(在 REDIS 命令和逻辑中),我接受他的贡献作为答案。
我的问题是我不知道设置密钥会重置过期时间。所以让它工作,正如 @for_stack 所解释的那样,涉及:
说明整体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);
}
完美运行!
这个方法对我有用
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);
例如:
这种方式不能设置过期时间:
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 秒的过期时间。