Heim  >  Artikel  >  Datenbank  >  Was sind die Vorteile von Redis->eval()?

Was sind die Vorteile von Redis->eval()?

藏色散人
藏色散人nach vorne
2019-06-13 14:13:512940Durchsuche

Verwenden Sie bei der Verwendung von Redis häufig get() und set()? Tatsächlich gibt es in Redis viele nützliche Datenstrukturen und verschiedene Methoden. Heute testen wir die Methode eval().

Empfohlen: „Redis Video Tutorial

Offizielle Redis Eval-Beschreibung (Auszug)

EVAL script numkeys key [key ...] arg [arg ...]

Von Redis 2.6.0 Ab Version 1 können Sie über den integrierten Lua-Interpreter den Befehl EVAL verwenden, um Lua-Skripte auszuwerten.

Redis verwendet einen einzigen Lua-Interpreter, um alle Skripte auszuführen, und Redis garantiert außerdem, dass Skripte auf atomare Weise ausgeführt werden: Wenn ein Skript ausgeführt wird, gibt es keine anderen Skripte oder Redis Der Befehl wird ausgeführt. Dies ist der Verwendung von MULTI/EXEC-umschlossenen Transaktionen sehr ähnlich. Aus Sicht anderer Clients sind die Auswirkungen des Skripts entweder nicht sichtbar oder bereits abgeschlossen.

Andererseits bedeutet dies aber auch, dass die Ausführung eines langsamen Skripts keine gute Idee ist. Es ist nicht schwer, ein Skript zu schreiben, das schnell und reibungslos läuft, da der Laufaufwand des Skripts sehr gering ist. Wenn Sie jedoch einige langsam laufende Skripte verwenden müssen, seien Sie bitte vorsichtig, denn wenn diese Schneckenskripte langsam sind, wann Wenn Sie Tuntundi ausführen, können andere Clients keine Befehle ausführen, da der Server ausgelastet ist.

Tatsächliche Messung

Mein Verständnis ist, dass die eval()-Methode in Redis im Allgemeinen in Szenarien verwendet wird, in denen mehrere Redis-Vorgänge ausgeführt werden müssen, um ein Ziel zu erreichen.

Unten habe ich ein Szenario simuliert, bei dem Redis 100 Mal ausgeführt wird. Natürlich ist dies in der Praxis möglicherweise nicht notwendig, ich möchte nur, dass jeder den Unterschied sieht.

<?php
 
$redis = new \Redis;
$redis->connect(&#39;127.0.0.1&#39;, 6379);
 
// 清空Redis
$redis->flushDB();
 
// PHP 中循环 set
$t = microtime(true);
for($i = 0; $i < 100; ++$i)
{
    $redis->set(&#39;key&#39; . $i, $i);
}
echo &#39;php for set: &#39;, microtime(true) - $t, PHP_EOL;
 
// 清空Redis
$redis->flushDB();
 
// 使用 eval 方法
$t = microtime(true);
$keys = [];
$values = [];
for($i = 0; $i < 100; ++$i)
{
    $keys[] = &#39;key&#39; . $i;
    $values[] = $i;
}
$redis->eval(<<<SCRIPT
for i=1,#KEYS do
    redis.call(&#39;set&#39;, KEYS[i], ARGV[i])
end
SCRIPT
, array_merge($keys, $values), count($keys));
echo &#39;eval:&#39;, microtime(true) - $t, PHP_EOL;

Ergebnis:

php for set: 0.056596040725708
eval:0.00089216232299805

Offensichtlich ist die Auswertung überwältigend schneller als die im Code festgelegte Schleife.

......

Glaubst du, das ist das Ende?

Nein!

evalSha, weißt du?

EvalSha-Beschreibung

EVALSHA sha1 numkeys key [key ...] arg [arg ...]

Bewerten Sie das im Server zwischengespeicherte Skript basierend auf dem angegebenen sha1-Prüfcode.

Das Zwischenspeichern von Skripten auf dem Server kann über den Befehl SCRIPT LOAD erfolgen.

Andere Aspekte dieses Befehls, wie z. B. die Methode zur Übergabe von Parametern, sind die gleichen wie beim EVAL-Befehl.

EvalSha tatsächliche Messung

<?php
function testEval($redis)
{
    $keys = [];
    $values = [];
    for($i = 0; $i < 100; ++$i)
    {
        $keys[] = &#39;key&#39; . $i;
        $values[] = $i;
    }
    $redis->eval(<<<SCRIPT
for i=1,#KEYS do
    redis.call(&#39;set&#39;, KEYS[i], ARGV[i])
end
SCRIPT
, array_merge($keys, $values), count($keys));
}
 
function testEvalSha($redis)
{
    $keys = [];
    $values = [];
    for($i = 0; $i < 100; ++$i)
    {
        $keys[] = &#39;key&#39; . $i;
        $values[] = $i;
    }
    $redis->evalSha(sha1(<<<SCRIPT
for i=1,#KEYS do
    redis.call(&#39;set&#39;, KEYS[i], ARGV[i])
end
SCRIPT
    ), array_merge($keys, $values), count($keys));
}
 
$redis = new \Redis;
$redis->connect(&#39;127.0.0.1&#39;, 6379);
 
// 清空Redis
$redis->flushDB();
 
// 使用 eval 方法
$t = microtime(true);
for($i = 0; $i < 100; ++$i)
{
    testEval($redis);
}
echo &#39;eval:&#39;, microtime(true) - $t, PHP_EOL;
 
 
// 清空Redis
$redis->flushDB();
 
// 使用 evalSha 方法
$t = microtime(true);
for($i = 0; $i < 100; ++$i)
{
    testEvalSha($redis);
}
echo &#39;evalSha:&#39;, microtime(true) - $t, PHP_EOL;

Ergebnis:

eval:0.081475973129272
evalSha:0.076005220413208

Nach den Ergebnissen meines Tests ist evalSha nicht schneller als eval Es gibt eine deutliche Verbesserung.

Wenn Sie jedoch in einer Produktionsumgebung evalSha verwenden, sendet es kleinere Datenpakete als eval und belegt weniger Netzwerkressourcen.

Weil eval jedes Mal das vollständige Skript an Redis senden muss, während evalSha nur einen sha1 übergeben muss.

evalSha kann nur direkt aufgerufen werden, nachdem eval einmal ausgeführt wurde.

Vorteile

Das Folgende ist eine Methode, die ich zuerst gekapselt habe, um es zu versuchen, und die Eval-Methode zu verwenden, wenn sie fehlschlägt.

/**
 * eval扩展方法,结合了 eval、evalSha
 * 
 * 优先使用 evalSha 尝试,失败则使用 eval 方法
 *
 * @param \Redis $redis
 * @param string $script
 * @param array $args
 * @param int $num_keys
 * @return mixed
 */
function evalEx($redis, $script, $args = null, $num_keys = null)
{
    $sha1 = sha1($script);
    $redis->clearLastError();
    $result = $redis->evalSha($sha1, $args, $num_keys);
    if(&#39;NOSCRIPT No matching script. Please use EVAL.&#39; === $redis->getLastError())
    {
        $result = $redis->eval($script, $args, $num_keys);
    }
    return $result;
}

Das obige ist der detaillierte Inhalt vonWas sind die Vorteile von Redis->eval()?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yurunsoft.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen
Vorheriger Artikel:So gruppieren Sie RedisNächster Artikel:So gruppieren Sie Redis