やあ。Redisの世界へようこそ。
Redisをただの「速いデータ置き場」だと思っているなら、それはまだ氷山の一角しか見ていないと言ってもいい。
今日は、Redisが単なる「箱」を超えて「頭脳」を持つための魔法、「Lua(ルア)スクリプト」について話そうと思う。初心者のみんなが躓きやすいポイントを、日常の風景に例えて紐解いていくから、安心してついてきてほしい。
—
1. なぜ「スクリプト」が必要なのか?(魔法のレストランの例え)
君が非常に人気のあるレストランの店長だと想像してほしい。
お客さんが「注文する」という動作には、実は裏でいくつかの手順があるよね。
1. 在庫を確認する
2. 在庫があれば減らす
3. 注文リストに名前を追加する
もし、この3つの手順をバラバラに実行しているとどうなるだろう?「注文の途中で別のスタッフが在庫を動かしてしまい、在庫切れなのに注文を受けてしまう」といった悲劇が起きるかもしれない。
これを防ぐには、「この3つの手順を、誰にも邪魔されず一気にやり遂げる」必要がある。これがRedisにおける「アトミック(不可分)な処理」だ。
RedisのLuaスクリプトを使えば、複雑な手順を一つの「おまじない」としてサーバーに送り込み、実行中に他の誰にも邪魔させず、一瞬で終わらせることができるんだ。
—
2. Luaスクリプトの基本的な道具たち
Redisには、この「おまじない」を扱うためのコマンドがいくつか用意されている。まずはこれだけ覚えておこう。
- `EVAL`: おまじないをその場で実行する。「今すぐこれをやって!」と命令する感じだね。
- `SCRIPT LOAD`: おまじないをサーバーに登録する。「この手順を覚えておいて」と教え込むこと。
- `EVALSHA`: 覚えたおまじないを呼び出す。「さっき教えた手順でやって!」と短縮して命令する。
—
3. やってみよう:在庫管理のコード
では、実際に簡単なコードを見てみよう。ここでは、「在庫が1つ以上あれば減らして、購入成功の印を出す」という処理を書いてみる。
— Luaスクリプトの例
— KEYS[1]は対象の商品、ARGV[1]は減らす数
local stock = tonumber(redis.call(‘get’, KEYS[1])) — 現在の在庫を取得
if stock > 0 then
redis.call(‘decr’, KEYS[1]) — 在庫を1つ減らす
return “OK: 購入完了”
else
return “Error: 売り切れです”
end
これを`EVAL`コマンドで実行するとこうなる。
商品「apple」の在庫を管理する例
1はKEYSの数、”apple”が対象キー
redis-cli EVAL “local stock = tonumber(redis.call(‘get’, KEYS[1])); if stock > 0 then redis.call(‘decr’, KEYS[1]); return ‘OK’; else return ‘Error’; end” 1 apple
どうだい?少し難しく見えるかもしれないが、やっていることは単純だ。「条件を確認して、実行する」という論理をサーバー側で完結させているだけなんだ。
—
4. なぜ「EVALSHA」が伝説のエンジニアに愛されるのか
`EVAL`で毎回長いスクリプトを送ると、ネットワークの帯域を無駄に消費してしまう。そこで登場するのが`SCRIPT LOAD`だ。
1. `SCRIPT LOAD`: 「この長い処理をサーバーに送るから、ハッシュ値(IDのようなもの)を返してくれ」
2. `EVALSHA
こうすれば、通信量は最小限になる。大規模なシステムになればなるほど、この「通信の節約」がパフォーマンスに直結するんだ。まさに、熟練のエンジニアが好むテクニックだね。
—
5. 最後に:無理して使わなくていい
ここまで読んでくれた君に、一つだけアドバイスがある。
Luaスクリプトは強力だが、「なんでもかんでもスクリプトに詰め込まないこと」が大事だ。
スクリプトが複雑すぎると、実行中は他の処理が待たされてしまい、Redis全体のパフォーマンスが落ちる可能性がある。あくまで「複数のコマンドをアトミックに実行したい時」の切り札として使ってほしい。
ここをマスターすれば、君はもうRedisの基礎を飛び越えて、「Redisを支配する側」に一歩近づいたことになる。
もし分からないことがあれば、いつでも聞いてくれ。エンジニアとしての旅路は長いが、焦らず一歩ずつ進めば、必ず素晴らしい景色が見えるはずだ。
応援しているよ。
コメント