【入門編】 スクリプトのアトミック性 – Redis

こんにちは!Redisの奥深い世界へようこそ。
今日は、Redisを語る上で避けて通れない、けれど初学者が最も「おや?」とつまずきやすいポイント——「Lua(ルア)スクリプトを使ったアトミック性(不可分性)」についてお話ししますね。

「難しそうな用語が出てきたな……」と思いましたか? 大丈夫です。
ここをクリアすれば、あなたもRedisの仕組みの本質をグッと掴めますよ。一緒に優しく紐解いていきましょう!

—

1. 日常の例え:レジ係の「お会計」で考えてみよう

まず、「アトミック(Atomic)」という言葉のイメージから始めましょう。エンジニアの世界でアトミックとは、「途中で分割できない、一連の処理がすべて成功するか、すべて無かったこと(ロールバック)になるかどちらかである性質」を指します。

これを、近所のコンビニのレジ係に例えてみます。

あなたが「100円のジュース」を買うとします。レジの仕事は次の2つですね。
1. 在庫のジュースを「1本減らす」
2. あなたの残高から「100円引く」

もし、1の処理が終わった瞬間に停電が起きて、2の処理ができなくなったらどうでしょう? お店は大損害ですし、お客さんにとっても理不尽ですよね。
だからレジ係は、「在庫を減らす」と「お金を引く」をセットで、一瞬で、途中で邪魔が入らないように処理しなければなりません。これが「アトミック」な状態です。

2. Redisと複数のコマンドのジレンマ

Redisは「超高速なメモリ上のデータベース」として有名ですが、実は標準の状態では、複数のコマンドを順番に実行しても、その間に「別の誰かの割り込み」が起きてしまいます。

例えば、こんな状況を想像してください。

  • あなたが「口座の残高を確認して、足りていれば引き出す」という処理をしたい。

これを普通のRedisコマンドでやろうとすると、
1. 「残高を読み込む」
2. (ここで別のプログラムが割り込んで、口座にお金を入れたり出したりする!)
3. 「残高から引き落とす」

という風に、間に割り込まれる隙(すき)が生まれてしまいます。これではデータがズタズタになってしまいますよね。

3. 救世主「Luaスクリプト」の登場

そこで登場するのが、Redisの中でプログラムを動かせるLuaスクリプト機能です。

Redisは、複雑な処理をひとまとめにした「スクリプト(台本)」を丸ごと受け取ることができます。そして、ここが一番大事なポイントなのですが……

Redisは、Luaスクリプトを実行している間、完全に「他のすべての処理をストップ(ブロック)」します。

先ほどのコンビニの例で言えば、レジ係があなたの精算の台本(Luaスクリプト)を受け取ったら、他のお客さんの列をピタッと止め、電卓を叩いて在庫と残高の計算を「一瞬(アトミック)」で終わらせてしまうイメージです。途中で他の人が割って入る隙は一切ありません。

4. 実際にコードを見てみよう

百聞は一見にしかず。簡単なLuaスクリプトの例を見てみましょう。
ここでは、「キーの値が特定の条件エンなら、値を書き換える」という処理をアトミックに行うスクリプトを書いてみます。

— Redis上で動くLuaスクリプトの例
— KEYS[1]: 対象のキー, ARGV[1]: 期待する値, ARGV[2]: 新しい値

local current_val = redis.call(‘get’, KEYS[1])

if current_val == ARGV[1] then
— 値が一致したら、新しい値に書き換える
redis.call(‘set’, KEYS[1], ARGV[2])
return “SUCCESS”
else
— 一致しなければ何もしない
return “FAILED”
end

ここがポイント:
`redis.call(…)` という命令を使って、RedisのコマンドをLuaスクリプトの中に閉じ込めています。
このスクリプトをRedisに投げると、Redisはこの中の処理を一気通貫で、誰にも邪魔されずに実行しきります。だから、データの矛盾が絶対に起きないのです。

5. 知っておくべき「ブロッキング特性」の裏側

さて、ここで鋭いあなたならこう気付くはずです。

  • 「Redisがスクリプト実行中に他の処理を止めるなら、もしそのスクリプトの処理がすごく長かったらどうなるの?」

その通り!非常に重要な着眼点です。
Redisは「シングルスレッド(基本的に同時に1つの仕事しかしない)」で動いています。そのため、重くて終わらないLuaスクリプトを流してしまうと、Redis全体がフリーズしたように止まってしまい、他のユーザーからのリクエストが一切処理できなくなります。(これが「ブロッキング特性」の裏側のリスクです)。

ですから、実務でLuaスクリプトを書くときの鉄則はこれです。
> 「Luaスクリプトの中身は、極限までシンプルに、一瞬で終わる処理だけにせよ!」

何万件ものループを回したり、重たい計算をLuaの中でやらせてはいけません。あくまで「複数のコマンドをアトミックにまとめるため」の外科手術のメスのようなものとして使いましょう。

—

おわりに

いかがでしたでしょうか?

  • アトミック性 = 途中で邪魔されない、すべてが一体となった処理。
  • Luaスクリプト = Redis上でそのアトミック性を手軽に実現する強力な武器。
  • ブロッキング特性 = 強力ゆえに、重い処理をさせるとRedis全体を止めてしまう諸刃の剣。

この概念さえ押さえておけば、Redisを使った高度な排他制御(ロック機構など)の仕組みもスッと理解できるようになります。

ここをクリアできれば、あなたのRedisの基本マスター度はグッと上がっていますよ!自信を持って次のステップへ進んでくださいね。それではまた!

コメント

タイトルとURLをコピーしました