Redis->eval() の利点は何ですか?

藏色散人
リリース: 2019-06-13 14:13:51
転載
2976 人が閲覧しました

Redis を使用するときに get() と set() をよく使用しますか?実際、Redis には便利なデータ構造とさまざまなメソッドが多数あります。今日は eval() メソッドをテストします。

推奨: 「Redis ビデオ チュートリアル

Redis Eval 公式説明 (抜粋)

EVAL script numkeys key [key ...] arg [arg ...]
ログイン後にコピー

Redis 2.6.0 よりバージョン 1 以降、組み込みの Lua インタープリターを通じて、EVAL コマンドを使用して Lua スクリプトを評価できるようになりました。

Redis は、単一の Lua インタープリターを使用してすべてのスクリプトを実行します。また、Redis は、スクリプトがアトミックな方法で実行されることも保証します。スクリプトの実行中、他のスクリプトや Redis コマンドは実行されません。これは、MULTI / EXEC で囲まれたトランザクションを使用するのと非常に似ています。他のクライアントの観点からは、スクリプトの効果は見えないか、すでに完了しています。

一方で、これは、遅いスクリプトを実行するのは得策ではないことも意味します。スクリプトの実行オーバーヘッドは非常に小さいため、高速かつスムーズに実行されるスクリプトを作成することは難しくありませんが、実行が遅いスクリプトを使用する必要がある場合は、注意してください。これらのカタツムリ スクリプトが遅い場合、 Tuntundi を実行すると、サーバーがビジー状態になるため、他のクライアントはコマンドを実行できなくなります。

実際の測定

私の理解では、Redis の eval() メソッドは通常、目標を完了するために複数の Redis 操作を実行する必要があるシナリオで使用されます。

以下では、redis を 100 回操作するシナリオをシミュレーションしました。もちろん、これは実際には必要ないかもしれません。違いを皆さんに見てもらいたいだけです。

<?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;
ログイン後にコピー

結果:

php for set: 0.056596040725708
eval:0.00089216232299805
ログイン後にコピー

明らかに、コード内でループを設定するよりも eval の方が圧倒的に高速です。

....

これで終わったと思いますか? ######いいえ!

evalSha 調べてみませんか?

EvalSha 説明

EVALSHA sha1 numkeys key [key ...] arg [arg ...]
ログイン後にコピー
指定された sha1 チェック コードに基づいて、サーバーにキャッシュされたスクリプトを評価します。

スクリプトをサーバーにキャッシュする操作は、SCRIPT LOAD コマンドを通じて実行できます。

このコマンドのその他の点 (パラメーターを渡す方法など) は、EVAL コマンドと同じです。

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;
ログイン後にコピー

結果:

eval:0.081475973129272
evalSha:0.076005220413208
ログイン後にコピー
私のテスト結果から、evalSha は eval より速くありません。大幅な改善。

ただし、実稼働環境では、evalSha を使用すると、eval よりも小さなデータ パケットが送信され、占有するネットワーク リソースが少なくなります。

eval は毎回完全なスクリプトを Redis に送信する必要があり、evalSha は sha1 を渡すだけでよいためです。

evalSha は、eval が 1 回実行された後でのみ直接呼び出すことができます。

利点

以下は私がカプセル化したメソッドです。最初は evalSha を使用して試し、失敗した場合は eval メソッドを使用してください。

rree

以上がRedis->eval() の利点は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yurunsoft.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート