PHPRedis Scan doesn't return the next cursor

1.3k views Asked by At

In my Laravel application, I used to use the predis/predis package to be able to use Redis for caching. Recently as recommended in the docs I have switched to PhpRedis but part of my code that was using SCAN is broken. In predis when I was using scan like this:

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

I used to get a result like this:

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

in this case 253952 was the next cursor that I could pass to scan again to get the next batch like this Redis::scan(253952,'match',$pattern //Test:*); and I could run this in a while loop until I reach the end:

$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);
}

Since I switched to Phpredis I can no longer iterate over the list. First of all the syntax seem to be different:

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

I'm not sure what is the point of passing null as iterator to the first parameter. It also just returns:

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

which is just part of the result. It doesn't give me everything and it doesn't give me the next cursor. Can someone please guide me in the right direction?

1

There are 1 answers

6
Ersoy On BEST ANSWER

I switched to Phpredis on my local and made it work with the following snippet. The documentation states that there are different usages of the scan.

$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;

While debugging or developing it would be useful to use monitor command. While that snippet is working it prints something like this;

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:*"