はじめに
この実験(Lab)では、Redis Lua スクリプティングについて探求します。特に、Lua スクリプトを Redis 内で直接実行し、複雑な操作を効率的に行うことに焦点を当てます。この実験(Lab)では、EVALコマンドを使用してスクリプトを実行する方法、スクリプトに引数を渡す方法、SCRIPT LOADでスクリプトをロードする方法、およびロードされたスクリプトをEVALSHAで実行する方法について説明します。
まず、EVALを使用して Redis カウンターをインクリメントする簡単な Lua スクリプトを実行し、スクリプト、アクセスするキーの数、およびキー名を指定する方法を示します。次に、スクリプトを Redis にロードし、SHA1 ハッシュを使用して実行する方法を学び、スクリプトの繰り返し送信を回避してパフォーマンスを向上させます。
EVAL で Lua スクリプトを実行
このステップでは、EVALコマンドを使用して、Redis 内で直接 Lua スクリプトを実行する方法を探求します。これにより、単一のリクエストでデータに対して複雑な操作を実行し、ネットワークレイテンシを削減し、パフォーマンスを向上させることができます。
始める前に、EVALの基本を理解しましょう。EVALコマンドは、主に 2 つの引数を取ります。
- Lua スクリプト自体(文字列として)。
- スクリプトがアクセスするキーの数、それに続く実際のキー名、およびスクリプトに渡したい追加の引数。
始めるための簡単な例を次に示します。Redis カウンターをインクリメントし、新しい値を返す Lua スクリプトを作成します。
ターミナルを開き、Redis コマンドラインインターフェース(
redis-cli)を使用して Redis サーバーに接続します。redis-cli次に、
EVALを使用して Lua スクリプトを実行します。このスクリプトは、mycounterという名前のカウンターをインクリメントし、インクリメントされた値を返します。EVAL "local current = redis.call('INCR', KEYS[1]); return current" 1 mycounterこのコマンドを分解してみましょう。
EVAL "local current = redis.call('INCR', KEYS[1]); return current": これは Lua スクリプト自体です。redis.call('INCR', KEYS[1])を使用して、KEYS[1]で指定されたキーの値をインクリメントします。KEYS配列には、スクリプトに渡されるキー名が含まれています。最後に、インクリメントされた値を返します。1: これは、スクリプトが 1 つのキーにアクセスすることを示します。mycounter: これは、スクリプトがアクセスするキーの名前です。
次のような出力が表示されるはずです。
(integer) 1同じコマンドをもう一度実行すると、カウンターがインクリメントされます。
EVAL "local current = redis.call('INCR', KEYS[1]); return current" 1 mycounter出力:
(integer) 2GETコマンドを使用して、mycounterキーの値を確認しましょう。GET mycounter出力:
"2"ご覧のとおり、Lua スクリプトはカウンターを正常にインクリメントしました。
次に、別の例を試してみましょう。今回は、キーが存在しない場合に、キーに特定の値が設定されるスクリプトを作成します。
EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end" 1 mykey myvalueこのコマンドでは:
EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end": これは Lua スクリプトです。キーKEYS[1]が存在するかどうかを確認します。存在しない場合は、キーに値ARGV[1]を設定し、1を返します。それ以外の場合は、0を返します。1: これは、スクリプトが 1 つのキーにアクセスすることを示します。mykey: これは、キーの名前です。myvalue: これは、キーが存在しない場合に設定する値です。
次のような出力が表示されるはずです。
(integer) 1これは、キー
mykeyがmyvalueに設定されたことを示します。mykeyの値を確認しましょう。GET mykey出力:
"myvalue"EVALコマンドをもう一度実行すると:EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end" 1 mykey myvalue出力:
(integer) 0今回は、キーがすでに存在するため、スクリプトは
0を返しました。redis-cliを終了します。これは、変更をログに記録するために重要です。exit
EVAL でスクリプトに引数を渡す
前のステップでは、EVALを使用して Lua スクリプトを実行し、キーにアクセスする方法を学びました。次に、これらのスクリプトに引数を渡す方法を探求しましょう。これにより、より動的で再利用可能なスクリプトが可能になります。
EVALコマンドは、次の引数を取ることを思い出してください。
- Lua スクリプト自体(文字列として)。
- スクリプトがアクセスするキーの数。
- キー名。
- スクリプトに渡したい追加の引数。これらの引数は、Lua スクリプト内で
ARGV配列を使用してアクセスされます。
例から始めましょう。Redis カウンターに値を追加する Lua スクリプトを作成します。カウンターのキーと追加する値は、引数として渡されます。
Redis コマンドラインインターフェース(
redis-cli)を使用して Redis サーバーに接続します。redis-cli次に、
EVALを使用して、指定された量だけカウンターをインクリメントする Lua スクリプトを実行します。EVAL "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current" 1 mycounter 5このコマンドを分解してみましょう。
EVAL "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current": これは Lua スクリプトです。redis.call('INCRBY', KEYS[1], ARGV[1])を使用して、KEYS[1]で指定されたキーの値を、ARGV[1]で指定された量だけインクリメントします。1: これは、スクリプトが 1 つのキーにアクセスすることを示します。mycounter: これは、スクリプトがアクセスするキーの名前です。5: これは、スクリプトに渡され、ARGV[1]としてアクセスされる引数です。
次のような出力が表示されるはずです(前のステップで
mycounterが 2 だったと仮定します)。(integer) 7スクリプトは、
mycounterキーを 5 だけインクリメントしました。GETコマンドを使用して、mycounterキーの値を確認しましょう。GET mycounter出力:
"7"次に、文字列引数を使用した別の例を試してみましょう。キーと値の両方が引数として渡される、キーに値を設定するスクリプトを作成します。
EVAL "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]" 1 mynewkey mynewvalueこのコマンドでは:
EVAL "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]": これは Lua スクリプトです。キーKEYS[1]に値ARGV[1]を設定し、値を返します。1: これは、スクリプトが 1 つのキーにアクセスすることを示します。mynewkey: これは、キーの名前です。mynewvalue: これは、設定する値です。
次のような出力が表示されるはずです。
"mynewvalue"mynewkeyの値を確認しましょう。GET mynewkey出力:
"mynewvalue"スクリプトは、キー
mynewkeyを値mynewvalueに正常に設定しました。スクリプトに複数の引数を渡すことができます。たとえば、引数として渡された 2 つの文字列を連結し、結果をキーに設定するスクリプトを作成しましょう。
EVAL "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result" 1 combinedkey hello worldこのコマンドでは:
EVAL "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result": これは Lua スクリプトです。..演算子を使用してARGV[1]とARGV[2]を連結し、キーKEYS[1]に結果を設定し、結果を返します。1: これは、スクリプトが 1 つのキーにアクセスすることを示します。combinedkey: これは、キーの名前です。hello: これは、最初の文字列引数です。world: これは、2 番目の文字列引数です。
次のような出力が表示されるはずです。
"helloworld"combinedkeyの値を確認しましょう。GET combinedkey出力:
"helloworld"redis-cliを終了します。これは、変更をログに記録するために重要です。exit
SCRIPT LOAD でスクリプトをロード
前のステップでは、EVALコマンドを使用して Lua スクリプトを直接実行しました。これは単純なスクリプトには便利ですが、より大きく複雑なスクリプトでは面倒になる可能性があります。Redis は、SCRIPT LOADコマンドを提供して、スクリプトを Redis サーバーのスクリプトキャッシュにロードします。これにより、スクリプト全体を毎回送信しなくても、スクリプトを複数回実行でき、パフォーマンスが向上します。
SCRIPT LOADコマンドは、単一の引数(Lua スクリプト自体)を取ります。スクリプトの SHA1 ハッシュを返し、EVALSHAコマンド(次のステップで説明します)を使用してスクリプトを実行するために使用できます。
どのように機能するか見てみましょう。
Redis コマンドラインインターフェース(
redis-cli)を使用して Redis サーバーに接続します。redis-cli次に、
SCRIPT LOADを使用して Lua スクリプトをロードします。前のステップと同じ、指定された量だけカウンターをインクリメントするスクリプトを使用します。SCRIPT LOAD "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current"このコマンドは、スクリプトを Redis サーバーのスクリプトキャッシュにロードし、スクリプトの SHA1 ハッシュを返します。次のような出力が表示されるはずです。
"6b1e8dd2999cb08546e74339c0c9489f9f89a84b"これは、スクリプトの SHA1 ハッシュです。次のステップで必要になるため、このハッシュをメモしておいてください。正確なハッシュ値は異なる場合があります。
次に、キーと値の両方が引数として渡される、キーに値を設定するスクリプトをロードしましょう。
SCRIPT LOAD "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]"次のような出力が表示されるはずです。
"a8b2b3648969459a8198262a9166e945e890987c"繰り返しますが、このハッシュをメモしておいてください。
引数として渡された 2 つの文字列を連結し、結果をキーに設定するスクリプトをロードしましょう。
SCRIPT LOAD "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result"次のような出力が表示されるはずです。
"d2a800a974ca96849295220424f9a0664a495345"このハッシュもメモしておいてください。
SCRIPT EXISTSコマンドを使用して、スクリプトがロードされていることを確認できます。このコマンドは、1 つ以上の SHA1 ハッシュを引数として取り、0 と 1 の配列を返します。1 は、対応するハッシュを持つスクリプトがロードされていることを示し、0 はロードされていないことを示します。たとえば、ロードした最初のスクリプトがまだロードされているかどうかを確認するには、次のコマンドを使用し、ハッシュをステップ 2 で取得したハッシュに置き換えます。
SCRIPT EXISTS 6b1e8dd2999cb08546e74339c0c9489f9f89a84b出力:
1) (integer) 1これは、スクリプトがロードされていることを示します。
ロードされていないスクリプトを確認しようとすると:
SCRIPT EXISTS 0000000000000000000000000000000000000000出力:
1) (integer) 0これは、スクリプトがロードされていないことを示します。
redis-cliを終了します。これは、変更をログに記録するために重要です。exit
EVALSHA でロードされたスクリプトを実行
前のステップでは、SCRIPT LOADコマンドを使用して Lua スクリプトを Redis サーバーのスクリプトキャッシュにロードする方法を学びました。次に、EVALSHAコマンドを使用して、ロードされたスクリプトを実行する方法を学びます。
EVALSHAコマンドは、次の引数を取ります。
- ロードされたスクリプトの SHA1 ハッシュ。
- スクリプトがアクセスするキーの数。
- キー名。
- スクリプトに渡したい追加の引数。
EVALSHAは、同じスクリプトを複数回実行する必要がある場合に、EVALよりも効率的です。これは、スクリプト全体を毎回サーバーに送信する必要がないためです。
どのように機能するか見てみましょう。
Redis コマンドラインインターフェース(
redis-cli)を使用して Redis サーバーに接続します。redis-cli次に、
EVALSHAを使用して、指定された量だけカウンターをインクリメントする Lua スクリプトを実行します。スクリプトlocal current = redis.call('INCRBY', KEYS[1], ARGV[1]); return currentの前のステップで取得した SHA1 ハッシュを覚えていますか?覚えていない場合は、SCRIPT LOADを使用してスクリプトを再度ロードする必要があります。この例では、ハッシュが6b1e8dd2999cb08546e74339c0c9489f9f89a84bであると仮定します。EVALSHA 6b1e8dd2999cb08546e74339c0c9489f9f89a84b 1 mycounter 5このコマンドを分解してみましょう。
EVALSHA 6b1e8dd2999cb08546e74339c0c9489f9f89a84b: これは、SHA1 ハッシュ6b1e8dd2999cb08546e74339c0c9489f9f89a84bを持つスクリプトを実行することを示します。1: これは、スクリプトが 1 つのキーにアクセスすることを示します。mycounter: これは、スクリプトがアクセスするキーの名前です。5: これは、スクリプトに渡され、ARGV[1]としてアクセスされる引数です。
次のような出力が表示されるはずです(前のステップで
mycounterが 7 だったと仮定します)。(integer) 12スクリプトは、
mycounterキーを 5 だけインクリメントしました。GETコマンドを使用して、mycounterキーの値を確認しましょう。GET mycounter出力:
"12"次に、
EVALSHAを使用して、キーに値を設定するスクリプトを実行しましょう。スクリプトredis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]の前のステップで取得した SHA1 ハッシュを覚えていますか?覚えていない場合は、SCRIPT LOADを使用してスクリプトを再度ロードする必要があります。この例では、ハッシュがa8b2b3648969459a8198262a9166e945e890987cであると仮定します。EVALSHA a8b2b3648969459a8198262a9166e945e890987c 1 anotherkey anothervalue次のような出力が表示されるはずです。
"anothervalue"anotherkeyの値を確認しましょう。GET anotherkey出力:
"anothervalue"無効な SHA1 ハッシュを持つスクリプトを実行しようとすると、エラーが発生します。
EVALSHA 0000000000000000000000000000000000000000 1 mykey myvalue出力:
(error) NOSCRIPT No matching script. Please use EVAL.これは、指定された SHA1 ハッシュを持つスクリプトがロードされていないことを示します。
redis-cliを終了します。これは、変更をログに記録するために重要です。exit
まとめ
この実験(Lab)では、Redis Lua スクリプトについて学習し、EVALコマンドを使用してスクリプトを直接実行することに焦点を当てました。EVALは、Lua スクリプトを文字列として、アクセスされるキーの数、およびキー名自体を引数として取ることを学びました。EVAL内の Lua スクリプトを使用して Redis カウンターをインクリメントする練習を行い、スクリプトが指定されたキーにアクセスして変更する方法を観察しました。
さらに、Lua スクリプトに引数を渡す方法、SCRIPT LOADを使用してスクリプトを Redis にロードする方法、およびEVALSHAを使用してロードされたスクリプトを実行する方法を学びました。コマンドが正しくログに記録されるように、各ステップの後にredis-cliを終了することを忘れないでください。これにより、複雑なスクリプトをより効率的に実行できます。


