Maison > base de données > Redis > le corps du texte

Quels sont les avantages de Redis->eval() ?

藏色散人
Libérer: 2019-06-13 14:13:51
avant
2938 Les gens l'ont consulté

Utilisez-vous souvent get() et set() lorsque vous utilisez Redis ? En fait, il existe de nombreuses structures de données utiles et diverses méthodes dans Redis. Aujourd'hui, nous allons tester la méthode eval().

Recommandé : "Tutoriel vidéo Redis"

Description officielle de Redis Eval (extrait)

EVAL script numkeys key [key ...] arg [arg ...]
Copier après la connexion

De Redis 2.6.0 À partir de la version 1, via l'interpréteur Lua intégré, vous pouvez utiliser la commande EVAL pour évaluer les scripts Lua.

Redis utilise un seul interpréteur Lua pour exécuter tous les scripts, et Redis garantit également que les scripts seront exécutés de manière atomique : lorsqu'un script est en cours d'exécution, il n'y aura pas d'autres scripts ou Redis La commande est exécutée. Ceci est très similaire à l’utilisation de transactions entourées MULTI/EXEC. Du point de vue des autres clients, les effets du script ne sont pas visibles ou sont déjà terminés.

D'un autre côté, cela signifie également qu'exécuter un script lent n'est pas une bonne idée. Il n'est pas difficile d'écrire un script qui s'exécute rapidement et sans problème, car la surcharge d'exécution du script est très faible, mais lorsque vous devez utiliser des scripts qui s'exécutent lentement, soyez prudent, car lorsque ces scripts escargot sont lents, lorsque exécutant Tuntundi, les autres clients ne pourront pas exécuter de commandes car le serveur est occupé.

Mesure réelle

Je crois comprendre que la méthode eval() dans Redis est généralement utilisée dans des scénarios où plusieurs opérations Redis doivent être effectuées pour atteindre un objectif.

Ci-dessous, j'ai simulé un scénario d'opération redis 100 fois. Bien sûr, cela n'est peut-être pas nécessaire en pratique, je veux juste que tout le monde voie la différence.

<?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;
Copier après la connexion

Résultat :

php for set: 0.056596040725708
eval:0.00089216232299805
Copier après la connexion

De toute évidence, eval est extrêmement plus rapide que la boucle définie dans le code.

......

Pensez-vous que c'est la fin ?

Non !

evalSha, vous connaissez ?

EvalSha Description

EVALSHA sha1 numkeys key [key ...] arg [arg ...]
Copier après la connexion

Évaluez le script mis en cache dans le serveur en fonction du code de vérification sha1 donné.

La mise en cache des scripts sur le serveur peut être effectuée via la commande SCRIPT LOAD.

Les autres aspects de cette commande, tels que la méthode de transmission des paramètres, sont les mêmes que la commande EVAL.

Mesure réelle d'EvalSha

<?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;
Copier après la connexion

Résultat :

eval:0.081475973129272
evalSha:0.076005220413208
Copier après la connexion

D'après mes résultats de test, evalSha n'est pas plus rapide que eval Il y a une amélioration significative.

Cependant, dans un environnement de production, si vous utilisez evalSha, il enverra des paquets de données plus petits qu'eval et occupera moins de ressources réseau.

Parce que eval doit envoyer le script complet à redis à chaque fois, alors que evalSha n'a besoin que de transmettre un sha1.

evalSha ne peut être appelé directement qu'après qu'eval ait été exécuté une fois.

Avantages

Ce qui suit est une méthode que j'ai encapsulée. Utilisez d'abord evalSha pour essayer, et utilisez la méthode eval si elle échoue.

/**
 * 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;
}
Copier après la connexion

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!

Étiquettes associées:
source:yurunsoft.com
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!