[已解决]关于Redis的SCAN命令请教?

Madman

问题描述

function scanKeys(string $pattern, int $count = 100): array
{
    $cursor = null;
    $keys = [];
    $redis = \support\Redis::connection();

    do {
        list($cursor, $fetchedKeys) = $redis->scan($cursor, ['MATCH' => $pattern, 'COUNT' => $count]);

        // 将当前批次的键添加到结果中
        $keys = array_merge($keys, $fetchedKeys);
    } while ($cursor > 0);

    return array_unique($keys);
}

$keys = scanKeys('data:*');
dump($keys);

这里的keys始终返回redis中所有的key,也就是'MATCH' => $pattern 始终是 'MATCH' => '*'

为此你搜索到了哪些方案及不适用的原因

在咨询了AI后他给出的提示是

游标 $cursor 初始化为 null,但 Redis 的 SCAN 通常期望初始值为 0。
没有对 $fetchedKeys 的空值进行防护,可能导致合并空数组时出现问题。
while ($cursor > 0) 可能不完全正确,因为 Redis 的游标可能返回非整数值(如字符串),应检查 $cursor !== 0。

AI给出修改后的代码如下

function scanKeys(string $pattern, int $count = 100): array
{
    $keys = [];
    $cursor = 0;
    $redis = \support\Redis::connection();

    do {
        $result = $redis->scan($cursor, ['MATCH' => $pattern, 'COUNT' => $count]);
        $cursor = $result[0] ?? 0;
        $fetchedKeys = $result[1] ?? [];

        $keys = array_merge($keys, $fetchedKeys);
    } while ($cursor !== 0);

    return array_unique($keys);
}

但改用这个函数后,keys始终为空...,不知道具体是哪里出了问题,求解答。

78 3 0
3个回答

orangeFan

测试了,当前方法虽然有值,但是过滤规则未生效
截图

后续:
截图
截图

  • Madman 23小时前

    终于搞定了,非常感谢

超高级的稻姬

框架内的options参数数组里取match和count是小写的

  • Madman 23小时前

    函数中有两点错误,一个是大小写,另外一个cursor初始应定义为null,非常感谢!

  • 超高级的稻姬 22小时前

    cursor是引用传递,这种参数在php当中可以不用定义初始值,它会自动被调用函数赋值,相似的类似preg_match函数的第三个参数

Madman
function scanKeys(string $pattern, int $count = 100): array
{
    $keys = [];
    $cursor = 0;
    $redis = \support\Redis::connection();

    do {
        // $result = $redis->scan($cursor, $pattern, $count); // 方法1
        $result = $redis->scan($cursor, ['match' => $pattern, 'count' => $count]); // 方法2
        $cursor = $result[0] ?? 0;
        $fetchedKeys = $result[1] ?? [];

        $keys = array_merge($keys, $fetchedKeys);
    } while ($cursor !== 0);

    return array_unique($keys);
}

两种方法都试了,结果都一样,测试代码如下

$keys = scanKeys('a:*');
dump(['scan', $keys]);

$keys = Redis::keys('a:*');
dump(['keys', $keys]);

打印结果为

×
🔝