Redisは非常に人気のあるメモリデータベースであり、データキャッシュや高頻度のデータストレージによく使用されます。ほとんどの開発者は、redisがLuaスクリプトを実行できると聞いたことがあるかもしれませんが、どのような状況でredisがLuaスクリプトを使用する必要があるのかわからない場合があります。
1.この記事を読むための前提条件
- このリンクの方法に従って、オペレーティングシステムにRedisをインストールできます。
- redisコマンドに慣れていない場合は、「Redisコマンドリファレンス」を確認してください。
2.なぜLuaスクリプトが必要なのですか
つまり、Luaスクリプトはパフォーマンスを向上させます。
- 多くのアプリケーションサービスタスクには、複数のredis操作と複数のredisコマンドの使用が含まれます。現時点では、RedisをLuaスクリプトと組み合わせて使用できるため、アプリケーションのパフォーマンスが向上します。
- さらに、Luaスクリプトに含まれるredisコマンドはアトミックです。同時実行性の高いシナリオでredisデータベース操作に直面した場合、マルチスレッド操作によって生成されるダーティデータを効果的に回避できます。
3つ目はLuaの構文を学ぶ
そんなに言ったので、ルアは何をしますか?慌てる必要はありません!Luaは実際には非常に単純です。プログラミング言語を学んだことがあれば、Luaの学習は非常に簡単です。学ぶためのいくつかの例を挙げましょう:
3.1。簡単な例
Luaスクリプトは、さまざまな言語のredisクライアントから呼び出すことができます。簡単に使用してみましょう。redis-cli
以下のredisコマンドラインをご覧ください。
eval "redis.call('set', KEYS[1], ARGV[1])" 1 key:name value
EVALコマンドラインの後にLuaスクリプトが続き"redis.call('set', KEYS[1], ARGV[1])"
ます。プログラミング言語に入力されるのは文字列であり、Luaスクリプト文字列に続く3つのパラメーターは次のとおりです。
- redisLuaスクリプトに必要なKEYSの数は1つだけのKEYS [1]であるため、スクリプト直後のパラメーター値は1です。
- Luaスクリプトに必要なパラメーターKEYS [1]のパラメーター値。この例では、値はkey:nameです。
- Luaスクリプトに必要なパラメーターARGV [1]のパラメーター値。この例では、値はvalueです。
Luaスクリプトには、KEYS []とARGV []の2つのパラメーターセットが含まれています。2つの配列の添え字は1から始まります。従う価値のあるベストプラクティスは、redis操作に必要なキーをKEYSを介してパラメーターとして渡し、他のLuaスクリプトに必要なパラメーターをARGVを介して渡すことです。
上記のスクリプトの実行が完了した後、次のLuaスクリプトを使用して検証します。スクリプトの戻り値が「value」である場合、これは前に設定したkey:nameの値と同じです。 Luaスクリプトは正しく実行されました。
eval "return redis.call('get', KEYS[1])" 1 key:name
3.2.Luaスクリプトの内容を詳しく見てみましょう
最初のLuaスクリプトには、次のステートメントが1つだけ含まれています。redis.call
redis.call('set', KEYS[1], ARGV[1])
したがって、Luaスクリプトではredis.call
、redisコマンドを実行できます。callメソッドの最初のパラメーターはredisコマンドの名前です。redissetコマンドを呼び出すため、キーと値のパラメーターを渡す必要があります。
getコマンドを実行すると実行結果も返されるため、2番目のスクリプトはスクリプトを実行するだけではありません。スクリプトにはreturnキーワードがあることに注意してください。
eval "return redis.call('get', KEYS[1])" 1 key:name
もちろん、上記のような単純なLuaスクリプトの場合は、コマンドラインを直接使用する方が便利です。実際に使用するLuaスクリプトは、上記よりも複雑になります。上記のLuaスクリプトは、HelloWorldにすぎません。
3.3。複雑な点の例
Luaスクリプトを使用して、ハッシュマップから特定の順序で複数のキーに対応する値を取得しました。対応する順序はzsetソートセットに保存され、データの設定とソートは次の方法で完了できます。
# 设置hkeys为键Hash值
hmset hkeys key:1 value:1 key:2 value:2 key:3 value:3 key:4 value:4 key:5 value:5 key:6 value:6
# 建一个order为键的集合,并给出顺序
zadd order 1 key:3 2 key:1 3 key:2
次のLuaスクリプトを実行します
eval "local order = redis.call('zrange', KEYS[1], 0, -1); return redis.call('hmget',KEYS[2],unpack(order));" 2 order hkeys
次の出力が表示されます
“value:3”
“value:1”
“value:2”
- zrangeを介して注文コレクションのデータを取得します。つまり、[key:3、key:1、key:2]
- 次に、アンパック関数を使用して、[key:3、key:1、key:2]をkey:3 key:1 key:2に変換します。
- 最後にhmgethkeys key:3 key:1 key:2を実行すると、上記の出力結果が得られます。
4、Luaスクリプトのプリロード
RedisはLuaスクリプトをプリロードでき、Luaスクリプトはscriptloadコマンドを使用してredisにプリロードできます。
script load "return redis.call('get', KEYS[1])"
プリロードが完了すると、次の出力が表示されます
“4e6d8fc8bb01276962cce5371fa795a7763657ae”
これは一意のハッシュ文字列です。このハッシュは、プリロードしたばかりのLuaスクリプトを表します。EVALSHAコマンドを使用してスクリプトを実行できます。といった:
evalsha 4e6d8fc8bb01276962cce5371fa795a7763657ae 1 key:name
実行結果は以下のとおりです。
eval "return redis.call('get', KEYS[1])" 1 key:name
5. JSONデータを変更する例は?
一部の開発者は、JSONデータをRedisに保存することがあります。これが良い方法かどうかは言わないでください。Luaスクリプトを使用してJSONデータを変更する方法について説明しましょう。
通常の状況では、JSONオブジェクトを変更する必要があり、redisからクエリを返し、解析し、キー値を変更してから、シリアル化してredisに保存する必要があります。これにはいくつかの問題があります。
- 同時実行性の高いシナリオでは、アトミック性を保証できません。別のスレッドが、現在のスレッドの取得とオブジェクト操作の設定の間でこのJSONデータを変更できます。この場合、更新は失われます。
- パフォーマンスの問題。このような変更を頻繁に行い、JSONデータが非常に大きい場合、これがアプリケーションのパフォーマンスのボトルネックになる可能性があります。データを頻繁にフェッチして保存するためです。
上記のロジックをLuaに実装することで、Redis Luaスクリプトはサーバー側で実行されるため、操作のアトミック性を確保し、同時実行性の高い更新が失われる問題を解決できます。一方、ネットワークを節約できます。送信し、パフォーマンスを向上させます。
次に、テストJSON文字列をredisに保存します。obj
set obj '{"a":"foo","b":"bar"}'
それでは、スクリプトを実行してみましょう。
EVAL 'local obj = redis.call("get",KEYS[1]); local obj2 = string.gsub(obj,"(" .. ARGV[1] .. "\":)([^,}]+)", "%1" .. ARGV[2]); return redis.call("set",KEYS[1],obj2);' 1 obj b bar2
local obj = redis.call("get",KEYS[1]);
ここで、KEYS [1] = objであるため、戻り値obj= '{"a":"foo","b":"bar"}'
local obj2 = string.gsub(obj,"(" .. ARGV[1] .. "\":)([^,}]+)", "%1" .. ARGV[2]);
、..
はLuaスクリプトの文字列連結記号です。正規表現パターンを使用してキーを照合し、その値を置き換えます。式に慣れていない場合は、独自のレッスンを作成してください。「%1」は最初に一致した部分文字列を意味します。「% 1 ".. ARGV [2]は" b ":" bar2 "と等しく、gsubを使用して置き換えます。
- 最後に、結果が返され、
obj
JSONオブジェクトの結果は次のようになります。
{"a":"foo","b":"bar2"}
6、まとめ
Luaスクリプトを使用することをお勧めするのは、パフォーマンスが向上することが証明できる場合のみです。redis操作のアトミック性を確保したいだけの場合は、トランザクションを使用できます。Luaスクリプトを使用する必要はありません。
さらに、redisLuaスクリプトは長すぎないようにする必要があります。スクリプトの実行中は、操作対象をロックするのと同じであり、他の操作はスクリプトが完了するのを待っているためです。Luaスクリプトの実行にかなりの時間がかかる場合、パフォーマンスが向上する代わりにボトルネックが発生する可能性があります。Luaスクリプトは、タイムアウト(デフォルトでは5秒)に達すると停止します。
私のブログをフォローすることを歓迎します、多くのブティックコレクションがあります
- この記事は、出典を示して複製されています(接続を添付する必要があり、テキストのみを複製することはできません):レターブラザーのブログ。
あなたがそれがあなたに役立つと思うなら、私のためにそれを好きにして共有してください!あなたのサポートは私の尽きることのない創造的な動機です!。また、最近、以下のような高品質なコンテンツを出力しておりますので、よろしくお願いいたします。