Maison >développement back-end >tutoriel php >Pièges rencontrés lorsque PHP utilise la commande redis scan

Pièges rencontrés lorsque PHP utilise la commande redis scan

不言
不言original
2018-04-04 09:39:425062parcourir


Dans les projets précédents, la commande keys de redis était utilisée pour obtenir certaines clés. Cette commande bloquera longtemps lorsque la base de données est particulièrement volumineuse, donc. Il existe d'énormes risques de sécurité, je prévois donc de l'optimiser cette fois.

Le site officiel recommande plutôt d'utiliser la commande scan. J'ai donc utilisé...


Voici le code pour utiliser la commande scan pour faire correspondre la clé du motif correspondant :

$redis = new Redis();
$redis->connect('localhost', 6379);

$iterator = null;while ($keys = $redis->scan($iterator, 'test*')) {    foreach ($keys as $key) {        echo $key . PHP_EOL;
    }
}

Ceci le code devrait être bon, non ? Ceci est extrait de la bibliothèque d'invites de code de phpstorm, un logiciel appartenant à la société jetbrains. Seul le paramètre pattern est ajouté, mais le résultat en cours d'exécution est problématique.

Pièges rencontrés lorsque PHP utilise la commande redis scan

En utilisant la commande keys, vous pouvez obtenir les cinq clés "test1", "test2",..., "test5" définies, mais rien n'est généré lors de l'utilisation de scan .

……

…………

…………

Après une analyse multipartite, il a finalement été découvert que la valeur de retour du La commande scan est une question.

En fait, le document officiel de redis indique aussi clairement que la commande scan peut renvoyer null à chaque itération, mais ce n'est pas un signe de fin, mais lorsque la valeur de l'itération renvoyée est "0" C'est la fin.

Par conséquent, lorsque le code ci-dessus est itéré, si aucune clé n'est renvoyée, $keys est un tableau vide, donc la boucle while est naturellement interrompue, donc il n'y a pas de sortie.

Cette situation est particulièrement évidente lorsqu'il y a beaucoup de clés dans Redis. Lorsqu'il n'y a que des dizaines ou des centaines de clés, cette situation se produit rarement, mais lorsque les clés atteignent des dizaines de millions, cette situation se produira presque certainement. .

Pour réduire l'apparition de cette situation, vous pouvez définir le troisième nombre de paramètres de la fonction de numérisation sur un nombre plus grand. Mais ce n'est pas la solution fondamentale à ce problème. Il existe deux solutions fondamentales :

1.setOption

通过setOption函数来设定迭代时的行为。以下是示例代码:

$redis = new Redis();
$redis->connect('localhost', 6379);
$redis->setOption(Redis::OPT_SCAN,Redis::SCAN_RETRY);

$iterator = null;while ($keys = $redis->scan($iterator, 'test*')) {    foreach ($keys as $key) {        echo $key . PHP_EOL;
    }
}

和上面的代码相比,只是多了个setOption的操作,这个操作的作用是啥呢?这个操作就是告诉redis扩展,当执行scan命令后,返回的结果集为空的话,函数不返回,而是直接继续执行scan命令,当然,这些步骤都是由扩展自动完成,当scan函数返回的时候,要么返回false,即迭代结束,未发现匹配模式pattern的key,要么就返回匹配的key,而不再会返回空数组了。

 

2.while(true)

上面那种方式是由php的扩展自动完成的,那么我们也可以换一种写法来达到相同的效果。

$redis = new Redis();
$redis->connect('localhost', 6379);

$iterator = null;while (true) {
    $keys = $redis->scan($iterator, 'test*');    if ($keys === false) {//迭代结束,未找到匹配pattern的key
        return;
    }    foreach ($keys as $key) {        echo $key . PHP_EOL;
    }
}

               

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn