Lua 初心者向けチュートリアル: https://www.runoob.com/lua/lua-tutorial.html
Redis で lua スクリプトを使用する利点:
- ネットワークのオーバーヘッドを削減します。複数のリクエストをスクリプトの形式で一度に送信して、ネットワークの遅延とオーバーヘッドを削減できます。
- アトミック操作。Redis はスクリプト全体を全体として実行し、他のリクエストによって途中に挿入されることはありません。したがって、スクリプトの実行中に競合状態を心配する必要はなく、トランザクションを使用する必要もありません。
- 再利用。クライアントから送信されたスクリプトは redis に永続的に保存されるため、他のクライアントはコードを使用せずにスクリプトを再利用して同じロジックを完了できます。
1. よく使われるコマンド
EVAL
: スクリプト スクリプトをスクリプト キャッシュに追加し、すぐにスクリプトを実行します- 文法:
EVAL script numkeys key [key …] arg [arg …]
- パラメータの意味:
- script : Lua5.1のスクリプトプログラムです。この Lua スクリプトは関数を定義する必要がなく、定義すべきではありません。Redis サーバーで実行されます。
- numkeys : キーパラメータの数。つまり、key [key ...] 内のキーの数です。キーがない場合は0
- key[] : スクリプトで使用される Redis キーを表すキー パラメーター これらのキー パラメーターは、Lua のグローバル変数 KEYS 配列を介して渡すことができます。lua スクリプトの KEYS[1]、KEYS[2] を通じて取得します。
- arg [arg …] : キーパラメータではない追加パラメータで、Lua のグローバル変数 ARGV 配列を通じてアクセスできます。lua スクリプトの ARGV[1]、ARGV[2] を通じて取得
- 場合
- set メソッドを呼び出します。
EVAL "return redis.call('set', 'name', 'bob')" 0
- set メソッドを呼び出します (パラメーターを使用)。
EVAL "return redis.call('set', KEYS[1], ARGV[1])" 1 name jack
- set メソッドを呼び出します。
- 文法:
EVALSHA
: 指定された SHA1 検証コードに基づいて、サーバーにキャッシュされたスクリプトを実行します。スクリプトをサーバーにキャッシュするには、SCRIPT LOAD
次のコマンドを使用します。パラメータの受け渡し方法など、このコマンドの他の部分はEVAL
コマンドと同じ です。- 文法:
EVALSHA sha1 numkeys key [key ...] arg [arg ...]
- 文法:
SCRIPT LOAD
: スクリプト スクリプトをスクリプト キャッシュに追加します。ただし、スクリプトはすぐには実行されません。スクリプトがキャッシュに追加されると、コマンド経由でEVALSHA
スクリプトのチェックサムを使用してスクリプトを呼び出すことができます。スクリプトは、SCRIPT FLUSH が実行されるまで無制限にキャッシュ内に保持されます。SHA1
- 文法:
SCRIPT LOAD script
。 - 戻り値: スクリプトの SHA1 チェックサム
- 文法:
SCRIPT EXISTS
: 指定したスクリプトがキャッシュに保存されているかどうかを確認します- 文法:
SCRIPT EXISTS sha1 [sha1 ...]
- 文法:
SCRIPT FLUSH
: Redis サーバー上のすべての Lua スクリプト キャッシュをクリアしますSCRIPT KILL
:現在実行中の Lua スクリプトを強制終了するために使用されます。このコマンドは、スクリプトが書き込み操作を実行していない場合にのみ有効になります。このコマンドは主に、バグにより無限ループするスクリプトなど、実行に時間がかかりすぎるスクリプトを終了するために使用されます。
場合:
redis 127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'" # 载入一个脚本
"232fd51614574cf0867b83d384a5e898cfd24e5a"
redis 127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
1) (integer) 1
redis 127.0.0.1:6379> SCRIPT FLUSH # 清空缓存
OK
redis 127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
1) (integer) 0
2. 特定のビジネスユースケース
Redis に基づく分散ロック
ロックを解除するプロセス:
- ロック内のスレッド ID を取得する
- 指定された ID (現在のスレッド ID) と一致するかどうかを判断します。
- 一貫性がある場合は削除し、一貫性がない場合は何もしません。
ロック解除.luaは次のとおりです。resources/unlock.lua
-- 比较线程标示与锁中的标示是否一致
if(redis.call('get', KEYS[1]) == ARGV[1]) then
-- 释放锁 del key
return redis.call('del', KEYS[1])
end
return 0
Java で呼び出すと次のようになります。
// 初始化 lua 脚本文件
private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
static {
UNLOCK_SCRIPT = new DefaultRedisScript<>();
//lua脚本位置
UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
//返回值类型
UNLOCK_SCRIPT.setResultType(Long.class);
}
// 使用 lua 脚本释放锁
public void unlock(String lockKey,String lockValue){
// 调用lua脚本
redisTemplate.execute(
UNLOCK_SCRIPT,
Collections.singletonList(lockKey),
lockValue);
}