やあ。Redisの深淵へようこそ。
世界中のエンジニアがその「爆速」の虜になるRedisだけど、今日はその中でも特に重要な「トランザクション(MULTI/EXEC)」と「楽観的ロック(WATCH)」という、いわばRedisの「誠実さ」を司る仕組みについて話そうと思う。
よくあるリファレンスの丸写しはしない。君が現場で「なぜこれが必要なのか」を腹落ちできるよう、日常の風景に例えて解説するよ。ついてきてくれ。
—
1. トランザクションとは何か?:カフェのレジを想像してほしい
Redisのトランザクションを一言で言うと、「一連の作業を『絶対にバラバラにしない』と誓う約束」だ。
想像してみてほしい。君がカフェでコーヒー(300円)を注文し、同時にポイントカードにスタンプ(1つ)を押してもらうとする。
もし、「コーヒーの料金は引かれたのに、スタンプは押されなかった」としたらどうかな? 悲しいよね。
これをプログラミングの世界では、「Aの処理とBの処理は、セットで成功するか、セットで失敗するかのどちらかでなければならない」と考える。これがトランザクションだ。
Redisでは、これを以下の3つの魔法のコマンドで実現する。
1. `MULTI`: 「今からセットでやるからね!」という宣言。
2. `コマンド群`: 実行したい操作を並べる(実際にはまだ実行されない)。
3. `EXEC`: 「よし、全部まとめて実行!」という合図。
実装のイメージ
1. 宣言開始
MULTI
OK
2. コマンドを予約(キューに溜まるだけで、まだ実行されない)
DECRBY user:1:balance 300
QUEUED
INCR user:1:points
QUEUED
3. 実行!
EXEC
1) (integer) 700 <- 残高が引かれた
2) (integer) 11 <- ポイントが増えた
`EXEC`を叩いた瞬間、Redisは「このセットは誰にも邪魔させない!」と、一気に処理を完遂してくれるんだ。
---
2. 「楽観的ロック(WATCH)」:ケンカを未然に防ぐ知恵
さて、ここからが本質だ。もし、君と別の誰かが同時に同じデータにアクセスしたらどうなる?
例えば、残高が1000円しかない口座から、君と友人が同時に「1000円引き出す」という処理をしたら、残高がマイナスになってしまうかもしれないよね。
これを防ぐためにRedisが持っているのが `WATCH` という機能だ。
「楽観的ロック」なんて小難しい名前がついているけれど、要は「私が作業している間に、誰かがこのデータをいじったら教えて!」という監視機能のことだ。
日常で例えると:
君が「この席(データ)を予約する!」と決めたとする。でも、もし君が座るまでの間に、他の誰かがその席に座ってしまったら?
その時は、「あ、先に誰かに取られちゃったから、予約はキャンセルだ!」と諦めて、最初からやり直すしかない。これが楽観的ロックの正体だ。
実装のイメージ
監視を開始(このキーが書き換えられたら通知してくれ!)
WATCH balance
ここで万が一、別の誰かが balance を書き換えると、
後の EXEC は失敗(nil)を返す仕組みになっている。
MULTI
DECRBY balance 1000
EXEC
もし監視中に誰かが書き換えていれば、ここは nil が返る。
その場合は、最初からやり直すのが鉄則だ。
—
3. なぜ「楽観的」なのか?
エンジニアがなぜこれを「楽観的」と呼ぶか、わかるかな?
それは、「ほとんどの場合は競合なんて起きないだろう」と楽観的に考えているからだ。
いちいち厳重に鍵をかけて作業を止める(悲観的ロック)のではなく、「とりあえず作業して、もし誰かが邪魔したらその時だけやり直せばいいよね」という合理的な考え方なんだ。これは、Redisのような超高速なシステムにとって、非常に賢い戦略なんだよ。
—
まとめ:君がマスターすべきこと
1. `MULTI / EXEC` は、一連の処理を「不可分な塊」にするためのもの。
2. `WATCH` は、データの整合性を守るための「見張り番」。
3. 「失敗したらやり直す」のが楽観的ロックの基本ルール。
この3つさえ押さえておけば、君はもうRedisのトランザクションを恐れる必要はない。
技術はただの道具だ。でも、その道具が「なぜその形をしているのか」を知っているエンジニアは、現場でどんなトラブルが起きても冷静に、かつスマートに解決できる。
ここをクリアできれば、君はもう一段階上のエンジニアに登れたはずだ。次は、Redisのデータ構造の真髄について話そうか。またいつでも聞きに来てくれ。応援しているよ。
コメント