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('127.0.0.1', 6379); // 清空Redis $redis->flushDB(); // PHP 中循环 set $t = microtime(true); for($i = 0; $i < 100; ++$i) { $redis->set('key' . $i, $i); } echo 'php for set: ', microtime(true) - $t, PHP_EOL; // 清空Redis $redis->flushDB(); // 使用 eval 方法 $t = microtime(true); $keys = []; $values = []; for($i = 0; $i < 100; ++$i) { $keys[] = 'key' . $i; $values[] = $i; } $redis->eval(<<<SCRIPT for i=1,#KEYS do redis.call('set', KEYS[i], ARGV[i]) end SCRIPT , array_merge($keys, $values), count($keys)); echo 'eval:', microtime(true) - $t, PHP_EOL;
結果:
php for set: 0.056596040725708 eval:0.00089216232299805
明らかに、コード内でループを設定するよりも eval の方が圧倒的に高速です。
....
これで終わったと思いますか? ######いいえ!
evalSha 調べてみませんか?
EvalSha 説明EVALSHA sha1 numkeys key [key ...] arg [arg ...]
スクリプトをサーバーにキャッシュする操作は、SCRIPT LOAD コマンドを通じて実行できます。
このコマンドのその他の点 (パラメーターを渡す方法など) は、EVAL コマンドと同じです。
EvalSha の実測値<?php
function testEval($redis)
{
$keys = [];
$values = [];
for($i = 0; $i < 100; ++$i)
{
$keys[] = 'key' . $i;
$values[] = $i;
}
$redis->eval(<<<SCRIPT
for i=1,#KEYS do
redis.call('set', KEYS[i], ARGV[i])
end
SCRIPT
, array_merge($keys, $values), count($keys));
}
function testEvalSha($redis)
{
$keys = [];
$values = [];
for($i = 0; $i < 100; ++$i)
{
$keys[] = 'key' . $i;
$values[] = $i;
}
$redis->evalSha(sha1(<<<SCRIPT
for i=1,#KEYS do
redis.call('set', KEYS[i], ARGV[i])
end
SCRIPT
), array_merge($keys, $values), count($keys));
}
$redis = new \Redis;
$redis->connect('127.0.0.1', 6379);
// 清空Redis
$redis->flushDB();
// 使用 eval 方法
$t = microtime(true);
for($i = 0; $i < 100; ++$i)
{
testEval($redis);
}
echo 'eval:', microtime(true) - $t, PHP_EOL;
// 清空Redis
$redis->flushDB();
// 使用 evalSha 方法
$t = microtime(true);
for($i = 0; $i < 100; ++$i)
{
testEvalSha($redis);
}
echo 'evalSha:', microtime(true) - $t, PHP_EOL;
ただし、実稼働環境では、evalSha を使用すると、eval よりも小さなデータ パケットが送信され、占有するネットワーク リソースが少なくなります。 eval は毎回完全なスクリプトを Redis に送信する必要があり、evalSha は sha1 を渡すだけでよいためです。 evalSha は、eval が 1 回実行された後でのみ直接呼び出すことができます。 以下は私がカプセル化したメソッドです。最初は evalSha を使用して試し、失敗した場合は eval メソッドを使用してください。 以上がRedis->eval() の利点は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。eval:0.081475973129272
evalSha:0.076005220413208