In früheren Projekten wurde der Befehl keys von redis verwendet, um bestimmte Schlüssel zu erhalten. Dieser Befehl blockiert für eine lange Zeit, wenn die Datenbank besonders groß ist Es gibt große Sicherheitsrisiken, daher habe ich vor, es dieses Mal zu optimieren.
Die offizielle Website empfiehlt stattdessen die Verwendung des Scan-Befehls. Also habe ich Folgendes verwendet:
Das Folgende ist der Code, um den Scan-Befehl zu verwenden, um den Schlüssel des entsprechenden Musters abzugleichen:
$redis = new Redis(); $redis->connect('localhost', 6379); $iterator = null;while ($keys = $redis->scan($iterator, 'test*')) { foreach ($keys as $key) { echo $key . PHP_EOL; } }
Dies Code sollte in Ordnung sein, oder? Dies stammt aus der Code-Prompt-Bibliothek von phpstorm, einer Software der Firma jetbrains. Es wurde nur der Musterparameter hinzugefügt, aber das Ausführungsergebnis ist problematisch.
Mit dem Tastenbefehl können Sie die fünf Tasten „test1“, „test2“, ..., „test5“ festlegen, bei Verwendung von scan wird jedoch nichts ausgegeben.
……
…………
…………
Nach einer Mehrparteienanalyse wurde schließlich festgestellt, dass der Rückgabewert des Scan-Befehl ist Frage.
Tatsächlich heißt es im offiziellen Dokument von Redis auch eindeutig, dass der Scan-Befehl für jede Iteration null zurückgeben kann. Dies ist jedoch kein Zeichen des Endes, sondern wenn der Wert der zurückgegebenen Iteration „0“ ist. Das ist das Ende.
Wenn also der obige Code iteriert und kein Schlüssel zurückgegeben wird, ist $keys ein leeres Array, sodass die while-Schleife natürlich unterbrochen wird und keine Ausgabe erfolgt.
Diese Situation ist besonders offensichtlich, wenn es in Redis viele Schlüssel gibt. Wenn es nur Dutzende oder Hunderte von Schlüsseln gibt, tritt diese Situation selten auf, aber wenn die Schlüssel Dutzende Millionen erreichen, wird diese Situation mit ziemlicher Sicherheit passieren .
Um das Auftreten dieser Situation zu reduzieren, können Sie die dritte Parameteranzahl der Scanfunktion auf eine größere Zahl einstellen. Dies ist jedoch nicht die grundlegende Lösung für dieses Problem. Es gibt zwei grundlegende Lösungen:
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; } }
Das obige ist der detaillierte Inhalt vonEs treten Fallstricke auf, wenn PHP den Redis-Scan-Befehl verwendet. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!