【问题标题】:Infinite loop when using predis SCAN使用 predis SCAN 时的无限循环
【发布时间】:2020-01-15 15:45:10
【问题描述】:

我正在尝试替换 predis 中的 keys 函数进行扫描,以提高我们所做的某些解析的性能。

问题是,当我执行扫描操作时,它似乎陷入了一个无限循环,这是没有意义的,因为根据 redis 文档,扫描完成后会将迭代器返回为 0。

        $it = null;
        $keysFound = [];

        do {

            $redisKeys = $redis->scan($it,"*{$query}", 10);

            if (!empty($keys)) {
                array_merge($keysFound, $redisKeys);
            }
        } while($it != 0);

我只是想替换它,所以我们不这样做

$keys = $redis->keys("*{$query}");

我都试过了,请大家帮忙。

更新 检查 cli 我发现它永远找不到密钥并保持循环,即使我放置了与 redsmin 中可以看到的完全相同的密钥。

127.0.0.1:6379> scan 122880 MATCH x_dashboard_dashboard_row_1005_251 
1) "118784"
2) (empty list or set)
127.0.0.1:6379> scan 118784 MATCH x_dashboard_dashboard_row_1005_251 
1) "18432"
2) (empty list or set)
127.0.0.1:6379> scan 18432 MATCH x_dashboard_dashboard_row_1005_251 
1) "59392"
2) (empty list or set)
127.0.0.1:6379> scan 59392 MATCH x_dashboard_dashboard_row_1005_251 
1) "63488"
2) (empty list or set)
127.0.0.1:6379> scan 63488 MATCH x_dashboard_dashboard_row_1005_251 
1) "123904"
2) (empty list or set)
127.0.0.1:6379> scan 123904 MATCH x_dashboard_dashboard_row_1005_251 
1) "19456"
2) (empty list or set)
127.0.0.1:6379> scan 19456 MATCH x_dashboard_dashboard_row_1005_251 
1) "121856"
2) (empty list or set)
127.0.0.1:6379> scan 121856 MATCH x_dashboard_dashboard_row_1005_251 
1) "115200"
2) (empty list or set)
127.0.0.1:6379> scan 115200 MATCH x_dashboard_dashboard_row_1005_251 
1) "119296"
2) (empty list or set)
127.0.0.1:6379> scan 119296 MATCH x_dashboard_dashboard_row_1005_251 
1) "109056"
2) (empty list or set)
127.0.0.1:6379> 

有没有可能被错误配置的东西?我以前从未使用过 redis,所以我不知道它是否可能与配置错误有关。

已解决 问题是我们有大量的键,因此将 COUNT 值增加到更大的数量会得到正确的结果。

【问题讨论】:

    标签: redis predis


    【解决方案1】:

    如果您想自己进行扫描,则需要从响应中捕获返回的光标:

    $it = null;
    $keysFound = [];
    
    do {
    
        $response = $redis->scan($it,"*{$query}", 10);
    
        $it = $response[0];
        $redisKeys = $response[1];
    
        if (!empty($keys)) {
            array_merge($keysFound, $redisKeys);
        }
    } while($it != 0);
    

    请参阅https://redis.io/commands/scan 以了解回复。

    但是看看迭代器,因为你可能正在重新发明轮子(取自How to use SCAN with the MATCH option in Predis,添加count):

    use Predis\Collection\Iterator;
    
    $client = ...;
    $pattern = 'foo*';
    $count = 100;
    
    foreach (new Iterator\Keyspace($client, $pattern, $count) as $key) {
        ...
    }
    

    【讨论】:

    • 我尝试了第一个选项,但在键返回内容时仍然得到空结果,还有其他想法吗?
    • 在少数几个扫描调用中没有密钥是可以的。您是否尝试过 redis-cli 上的扫描命令来解决可能出现的问题?你可以在 Redis-cli 上尝试 MONITOR 命令并运行你的 php 代码,看看有什么不同
    • 嗨 LeoMurillo 感谢您的回复,我尝试了命令 redis-cli(我无法尝试 MONITOR,因为生产执行了太多 redis 调用而无法看到某些内容)。我刚刚更新了帖子,如果您能看一下,我将不胜感激。
    • x_dashboard_dashboard_row_1005_251 没有模式匹配的通配符,因此只会检索整个空间中的一个键。只要您有光标,您的扫描就会取得进展。见Redis SCAN: how to maintain a balance ...?,甚至可以根据光标计算进度百分比
    猜你喜欢
    • 1970-01-01
    • 2015-04-17
    • 2020-01-31
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多