【问题标题】:PHPRedis Scan doesn't return the next cursorPHPRedis Scan 不返回下一个游标
【发布时间】:2021-02-03 20:15:17
【问题描述】:

在我的 Laravel 应用程序中,我曾经使用 predis/predis 包来使用 Redis 进行缓存。最近,按照文档中的建议,我已切换到 PhpRedis,但我使用 SCAN 的部分代码已损坏。在predis中,当我像这样使用扫描时:

Redis::scan(0,'match',$pattern //Test:*);

我曾经得到这样的结果:

[
     "253952",
     [
       "Test::296589",
       "Test::299112",
       "Test::332487",
       "Test::320358",
     ],
   ]

在这种情况下,253952 是下一个光标,我可以通过它再次扫描以获取像这样的下一批 Redis::scan(253952,'match',$pattern //Test:*); 我可以在一个while循环中运行它,直到我到达终点:

$all_keys = [];
$keys = RedisManager::scan(0, 'match', $pattern);
while ($keys[0] !== "0") {
   foreach($keys[1] as $key) {
      $all_keys[] = $key;
   }
 $keys = RedisManager::scan($keys[0], 'match', $pattern);
}

自从我切换到 Phpredis 后,我无法再遍历列表。首先语法似乎不同:

$it=null;
$keys = RedisManager::scan($it,$pattern);

我不确定将 null 作为迭代器传递给第一个参数有什么意义。它也只是返回:

[
 "Test::296589",
 "Test::299112"
]

这只是结果的一部分。它没有给我一切,也没有给我下一个光标。有人可以指导我正确的方向吗?

【问题讨论】:

    标签: laravel redis predis phpredis


    【解决方案1】:

    我在本地切换到 Phpredis 并使其与以下 sn-p 一起工作。 documentation 表示扫描有不同的用法。

    $redis = RedisManager::connection(); // initialize
    
    $redis->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY); // please check documentation for other option
    $keyList = [];
    $iterator = null;
    
    // you may update the count or match options according to your needs
    while ($keys = $redis->scan($iterator, ['match' => 'Test:*', 'count' => 20])) {
        $iterator = $keys[0];
        foreach ($keys[1] as $key) {
            $keyList[] = $key;
        }
    }
    
    return $keyList;
    

    在调试或开发时,使用monitor 命令会很有用。虽然该 sn-p 正在工作,但它会打印出类似这样的内容;

    1603241935.261667 [0 127.0.0.1:52536] "SCAN" "0" "COUNT" "20" "MATCH" "Test:*"
    1603241935.262241 [0 127.0.0.1:52536] "SCAN" "48" "COUNT" "20" "MATCH" "Test:*"
    1603241935.263421 [0 127.0.0.1:52536] "SCAN" "424" "COUNT" "20" "MATCH" "Test:*"
    1603241935.264476 [0 127.0.0.1:52536] "SCAN" "260" "COUNT" "20" "MATCH" "Test:*"
    1603241935.265508 [0 127.0.0.1:52536] "SCAN" "100" "COUNT" "20" "MATCH" "Test:*"
    1603241935.266405 [0 127.0.0.1:52536] "SCAN" "460" "COUNT" "20" "MATCH" "Test:*"
    1603241935.267137 [0 127.0.0.1:52536] "SCAN" "258" "COUNT" "20" "MATCH" "Test:*"
    1603241935.268271 [0 127.0.0.1:52536] "SCAN" "402" "COUNT" "20" "MATCH" "Test:*"
    1603241935.269344 [0 127.0.0.1:52536] "SCAN" "42" "COUNT" "20" "MATCH" "Test:*"
    1603241935.270328 [0 127.0.0.1:52536] "SCAN" "198" "COUNT" "20" "MATCH" "Test:*"
    1603241935.275193 [0 127.0.0.1:52536] "SCAN" "342" "COUNT" "20" "MATCH" "Test:*"
    1603241935.276690 [0 127.0.0.1:52536] "SCAN" "286" "COUNT" "20" "MATCH" "Test:*"
    1603241935.279386 [0 127.0.0.1:52536] "SCAN" "510" "COUNT" "20" "MATCH" "Test:*"
    1603241935.281084 [0 127.0.0.1:52536] "SCAN" "81" "COUNT" "20" "MATCH" "Test:*"
    1603241935.282568 [0 127.0.0.1:52536] "SCAN" "41" "COUNT" "20" "MATCH" "Test:*"
    1603241935.284090 [0 127.0.0.1:52536] "SCAN" "185" "COUNT" "20" "MATCH" "Test:*"
    1603241935.285949 [0 127.0.0.1:52536] "SCAN" "117" "COUNT" "20" "MATCH" "Test:*"
    1603241935.288443 [0 127.0.0.1:52536] "SCAN" "253" "COUNT" "20" "MATCH" "Test:*"
    1603241935.293034 [0 127.0.0.1:52536] "SCAN" "147" "COUNT" "20" "MATCH" "Test:*"
    1603241935.294957 [0 127.0.0.1:52536] "SCAN" "155" "COUNT" "20" "MATCH" "Test:*"
    1603241935.296113 [0 127.0.0.1:52536] "SCAN" "199" "COUNT" "20" "MATCH" "Test:*"
    1603241935.296456 [0 127.0.0.1:52536] "SCAN" "247" "COUNT" "20" "MATCH" "Test:*"
    1603241935.296723 [0 127.0.0.1:52536] "SCAN" "223" "COUNT" "20" "MATCH" "Test:*"
    

    【讨论】:

    • 感谢您的回复。当我运行您的代码时,我收到此错误PHP Warning: Redis::scan() expects parameter 2 to be string, array given in /var/www/api/vendor/laravel/framework/src/Illuminate/Redis/Connections/Connection.php on line 114
    • @HiradRoshandel 可能版本不同,请将scan($iterator, ['match' => 'Test:*', 'count' => 20] 替换为scan($iterator, 'Test:*', 20) prnt.sc/v3gkjc PhpRedisConnection 类中方法的文档可能会给出一些提示。
    • $keys = $redis->scan($iterator, 'Test:*', 20) 只返回一个字符串数组 ["Test::296589","Test::299112"] 这使得 forloop 中断。我想知道为什么我们会得到不同的结果。您的代码是为 Predis 输出 Scan 的方式编写的。
    • 忘了说我使用的是 laravel 5.8。不确定这是否会有所作为。在 PhpRedisConnection.php 我没有任何 scan 函数
    • 如果您使用 \Generator,$redis->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY); 很有用。
    猜你喜欢
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多