マスター Redis Lua スクリプト:パフォーマンスを向上させるための実践ガイド
アンドレイ・チェルニコフ著
Redis は、プロセス間通信とデータ ストレージに使用される一般的なメモリ内グリッドです。 Lua スクリプトを実行できるということは聞いたことがあるかもしれませんが、その理由はまだわかりません。そう思われる方は、読み進めてください。
前提条件
このガイドに従うには、システムに Redis がインストールされている必要があります。読んでいるときに Redis コマンド リファレンスを確認すると役立つかもしれません。
Lua スクリプトが必要なのはなぜですか?
一言で言えば、パフォーマンスの向上です。 Redis で実行するほとんどのタスクには多くの手順が含まれます。これらの手順をアプリケーションの言語で実行する代わりに、Lua を使用して Redis 内で実行できます。
- これによりパフォーマンスが向上する可能性があります。
- また、スクリプト内のすべてのステップはアトミックな方法で実行されます。スクリプトの実行中は、他の Redis コマンドを実行できません。
たとえば、Lua スクリプトを使用して、Redis に保存されている JSON 文字列を変更します。これについては、この記事の最後の方で詳しく説明します。
でも、Lua はまったく知りません
LUA をまったく知らない人
心配しないでください。Lua を理解するのはそれほど難しくありません。 C ファミリーの言語を知っていれば、Lua を使用しても大丈夫です。また、この記事では実際の例も提供しています。
例を見せてください
まず、redis-cli 経由でスクリプトを実行しましょう。 。以下で始めてください:
redis-cli
次に、次のコマンドを実行します。
eval “redis.call(‘set’, KEYS[1], ARGV[1])” 1 key:name value
評価 コマンドは、Redis に後続のスクリプトを実行するように指示します。 ”redis.call(‘set’, KEYS[1], ARGV[1])” string は、Redis の set と機能的に同一のスクリプトです。 コマンド。スクリプト テキストの後に 3 つのパラメータが続きます。
スクリプト引数は 2 つのグループに分類されます:キー とARGV .
スクリプトに必要なキーの数を直後の数字で指定します。この例では、1 です。 。この番号の直後に、これらのキーを順番に入力する必要があります。これらはキーとしてアクセスできます。 スクリプト内のテーブル。この例では、単一の値 key:name が含まれています。 インデックス 1 .
Lua インデックス付きテーブルはインデックスで始まることに注意してください 1、 そうではありません 0 .
キーの後に任意の数の引数を指定できます。これは Lua でARGV として使用できます。 テーブル。この例では、単一のARGVを提供します。 -引数:文字列 value 。すでにご想像のとおり、上記のコマンドはキー key:name を設定します。 値 value に設定 .
スクリプトがキーとして使用するキーを提供することをお勧めします。 、および他のすべての引数は ARGV として指定されます。 。したがって、KEYS を指定しないでください。 0 として指定し、ARGV 内のすべてのキーを指定します。 テーブル。
スクリプトが正常に完了したかどうかを確認してみましょう。これを行うには、Redis からキーを取得する別のスクリプトを実行します。
eval "return redis.call('get', KEYS[1])" 1 key:name
出力は ”value” となるはずです。 これは、前のスクリプトがキー “key:name” を正常に設定したことを意味します。 .
スクリプトについて説明していただけますか?
上記のスクリプトを見た後、Doge してください
最初のスクリプトは 1 つのステートメント、redis.call で構成されています。 関数:
redis.call(‘set’, KEYS[1], ARGV[1])
redis.call を使用 任意の Redis コマンドを実行できます。最初の引数は、このコマンドの名前とその後に続くパラメータです。 set の場合 コマンドでは、これらの引数が重要です。 そして価値 。すべての Redis コマンドがサポートされています。ドキュメントによると:
Redis は同じ Lua インタープリターを使用してすべてのコマンドを実行します
2 番目のスクリプトは、単一のコマンドを実行するだけではなく、値も返します。
eval “return redis.call(‘get’, KEYS[1])” 1 key:name
スクリプトによって返されたものはすべて、呼び出し元のプロセスに送信されます。私たちの場合、このプロセスはredis-cli です。 ターミナル ウィンドウに結果が表示されます。
もっと複雑なことはありますか?
複雑な Redis スクリプトの構築を計画している人
私はかつて Lua スクリプトを使用して、ハッシュ マップから要素を特定の順序で返しました。順序自体は、ソートされたセットに格納されたハッシュ キーによって指定されました。
まず、redis-cli で次のコマンドを実行してデータを設定しましょう。 :
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
zadd order 1 key:3 2 key:1 3 key:2
これらのコマンドは、キー hkeys でハッシュ マップを作成します。 キー order のソートされたセット hkeys から選択されたキーが含まれています
確認してみるとよいでしょう hmset そして ザッド 詳細についてはコマンド リファレンスを参照してください。
次のスクリプトを実行してみましょう:
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”
これは、必要なキーの値を正しい順序で取得したことを意味します。
実行するにはスクリプトの完全なテキストを指定する必要がありますか?
いや! Redis では、SCRIPT LOAD を使用してスクリプトをメモリにプリロードできます。 コマンド:
script load “return redis.call(‘get’, KEYS[1])”
次のような出力が表示されるはずです。
“4e6d8fc8bb01276962cce5371fa795a7763657ae”
これは、EVALSHA に提供する必要があるスクリプトの一意のハッシュです。 スクリプトを実行するコマンド:
evalsha 4e6d8fc8bb01276962cce5371fa795a7763657ae 1 key:name
注:実際のを使用する必要があります。 SHA1 によって返されたハッシュ スクリプトロード コマンド、上記のハッシュは単なる例です。
JSON の変更について何と言いましたか?
場合によっては、JSON オブジェクトを Redis に保存することがあります。それが良いアイデアかどうかは別の話ですが、実際にはこのようなことはよく起こります。
この JSON オブジェクトのキーを変更する必要がある場合は、Redis からキーを取得し、解析してキーを変更し、シリアル化して Redis に設定し直す必要があります。このアプローチにはいくつかの問題があります。
<オル>
テスト JSON 文字列をキー obj の下の Redis に追加しましょう :
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
これで、キー obj の下に次のオブジェクトが作成されます。 :
{“a”:”foo”,”b”:”bar2"}
代わりに、SCRIPT LOAD を使用してこのスクリプトをロードできます。 コマンド:
SCRIPT LOAD ‘local obj = redis.call(“get”,KEYS[1]); local obj2 = string.gsub(obj,”(“ .. ARGV[1] .. “\”:)([^,}]+)”, “%1” .. ARGV[2]); return redis.call(“set”,KEYS[1],obj2);’
そして、次のように実行します。
EVALSHA <your_script_sha> 1 obj b bar2
いくつかの注意事項:
..は、Lua の文字列連結演算子です。- 正規表現パターンを使用してキーを照合し、その値を置き換えます。この正規表現がわからない場合は、私の最近のガイドを確認してください。
- Lua RegEx フレーバーが他のほとんどのフレーバーと異なる点の 1 つは、
%を使用することです。 RegEx 特殊記号の後方参照マークとエスケープ文字の両方として使用します。 - まだ
”をエスケープしています\を使用%ではありません RegEx の特殊記号ではなく、Lua 文字列区切り文字をエスケープするためです。
常に Lua スクリプトを使用する必要がありますか?
いいえ。パフォーマンスが向上することが証明できる場合にのみ使用することをお勧めします。常に最初にベンチマークを実行してください。
原子性だけが必要な場合は、代わりに Redis トランザクションをチェックする必要があります。
また、スクリプトは長すぎてもいけません。スクリプトの実行中は、他のすべてがスクリプトの終了を待っていることに注意してください。スクリプトにかなりの時間がかかる場合、パフォーマンスが向上する代わりにボトルネックが発生する可能性があります。スクリプトはタイムアウト (デフォルトでは 5 秒) に達すると停止します。
Redis スクリプトには時間がかかりすぎないようにする必要があります
最後の言葉
Lua の詳細については、lua.org を確認してください。
Lua スクリプトの例については、GitHub で私の Node.js ライブラリを確認してください (src/lua を参照) フォルダー)。また、node.js でこのライブラリを使用して、Lua スクリプトを自分で作成せずに JSON オブジェクトを変更することもできます。
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
この記事をお読みいただきありがとうございます。ご質問やご意見をお待ちしております。フォローも大歓迎です。 Twitter で .
無料でコーディングを学びましょう。 freeCodeCamp のオープンソース カリキュラムは、40,000 人以上の人々が開発者としての職に就くのに役立ちました。始めましょう
-
Redis Enterpriseはお金を節約できますか?
Redisはインメモリデータベースであり、Redis Enterpriseはその上に管理、自動化、復元力、セキュリティ機能の全層を追加して、エンタープライズ対応にします。多くの人にとって、メモリ内は「高価」、つまり最高のパフォーマンスに対して支払うことを選択したプレミアムに相当します。また、エンタープライズソフトウェアによって提供される機能は、高額な値札をもたらす可能性もあります。では、このようなテクノロジーがどのようにしてコスト削減の手段になるのでしょうか。 その質問に深く方法論的に答えるために、私たちはその分野の最高の専門家であるForresterConsultingとそのTotalE
-
RedisDaysLondon2022の概要
3部構成の世界規模のバーチャルイベントであるRedisDaysは、今年ロンドンに立ち寄り、Redisの専門家と尊敬されるゲストがミリ秒未満の速度の力を深く掘り下げました。 RedisDaysは、リアルタイムデータの新製品の発表、ベストプラクティス、新しい顧客のユースケースとともに、過去1年間に行ったすべての学習と技術的進歩をコミュニティと共有する機会です。以下は、RedisDaysLondon2022のハイライトの一部です。 基調講演:リアルタイムの時代は今です。加速するか混乱する Redisの共同創設者兼CEOであるOferBengalは、基調講演で物事を開始しました。基調講演は、1