【入門編】 トランザクションマネージャーの内部動作 – Cloud Spanner

こんにちは!Cloud Spannerの世界へようこそ。
伝説のチーフアーキテクト……なんて呼ばれることもありますが、今日は堅苦しい数式や難解な専門用語の代わりに、誰もが日常で経験する「あるシチュエーション」を使って、Cloud Spannerの心臓部である「トランザクションマネージャー」の秘密を解き明かしていきますね。

ここをクリアすれば、Cloud Spannerの分散データベースとしてのすごみと、データの一貫性を保つ仕組みがバッチリマスターできますよ。それでは、コーヒー片手にリラックスして聞いてください。

—

分散データベースの「お買い物」で考えてみよう

突然ですが、あなたと友人の2人で、世界中にある支店から同時に「最後の一点限りの大人気スニーカー」を買おうとしたとします。

普通のデータベースだと、「あれ?東京の店舗でも売れたし、ニューヨークの店舗でも売れちゃった!在庫がマイナスに……」なんて大パニックが起きますよね。

Cloud Spannerは、地球の裏と表にあるような巨大なサーバーたちが協力してデータを守る「分散データベース」です。この巨大なチームワークを統率し、「世界中のどこからアクセスしても、絶対に矛盾が起きないようにする」のを取り仕切っているのが、今回主役の「トランザクションマネージャー(コーディネーター)」です。

—

トランザクションマネージャーって、例えるとどんな人?

トランザクションマネージャーの役割は、結婚式の「敏腕ウエディングプランナー」や、壮大なプロジェクトを率いる「超優秀なプロジェクトマネージャー」にそっくりです。

彼らの仕事は、「全員の足並みをそろえて、物事を完全に成功させる(あるいは、何か問題があれば最初から無かったことにする)」こと。

Cloud Spannerでは、この調整役をどうやっているのか、ライフサイクルに沿って見ていきましょう。

—

2相コミット(2PC):ふたりの息を合わせる奇跡のステップ

分散システムの世界で、複数のサーバー(データが置いてある場所)に「同時にデータを書き込んでね」と頼むのは、実はめちゃくちゃ難しいことです。途中で片方のサーバーの電源が落ちたり、ネットワークが切れたりするかもしれないからです。

そこで登場するのが、2相コミット(Two-Phase Commit / 2PC)という仕組みです。名前は難しそうですが、要は「準備(Prepare)」と「本番(Commit)」の2段階で確認し合うだけのシンプルなステップです。

日常の例で言うと、「友達とサプライズパーティーを成功させる約束」に似ています。

第1段階:準備フェーズ(みんな、心の準備はいいかい?)

コーディネーター役のトランザクションマネージャーが、データを持っている各サーバー(参加者)のところへ走り回り、こう言います。

> 「ねえ、これから『スニーカーの在庫を1つ減らして、購入履歴を増やす』っていう大事な処理をしたいんだけど、君の担当分のデータ、今なら書き込める? 準備できたら『OK』って言ってね」

これに対し、各サーバーは自分の手元をチェックして、問題なければ「OK(準備完了)」と返事をします。もし誰かが「あ、ごめん、今ロックがかかってて無理!」と言ったら、この時点で計画は中止になります。

第2段階:コミットフェーズ(せーので、本番スタート!)

全員から「OK」の返事をもらったコーディネーターは、ここで初めてこう宣言します。

> 「よし、全員準備OKだね! それじゃあ、せーの!で書き込みを実行して!」

この瞬間、世界中に散らばるサーバーが一斉にデータを書き換えます。全員が無事に書き終えたら、トランザクションマネージャーは「お疲れ様でした!これにて一件落着です!」と取引を完了させます。

これが、Cloud Spannerが世界規模の巨大なシステムでありながら、銀行の通帳記帳のように正確なデータを保てる理由の裏側です。

—

失敗したときは?(アボートの美学)

もし、第1段階の準備フェーズで、サーバーの1台が「ネットワークが不安定で書き込めないよ!」と音を上げたらどうなるでしょうか?

ここで中途半端に「半分だけ書き換わっている」状態になると、データの世界は大混乱に陥ります(お金が消えたり増えたりする悪夢です)。

しかし、そこはさすがのトランザクションマネージャー。
1台でも「無理」と言ったら、即座に全員へ「アボート(Abort=中止)!」の号令をかけます。

これにより、すべてのサーバーは「さっきの変更はなかったことにする(ロールバック)」という安全な状態に戻ります。「やるなら全員で完璧にやる。無理なら一切やらない」。これが、データの世界における絶対の鉄則なのです。

—

コードから見る「トランザクション」の優しさ

Cloud Spannerを実際に触るとき、私たちはこの複雑な2相コミットやトランザクションマネージャーの苦労を、意識する必要がほとんどありません。SDKがすべて裏側でよしなにやってくれるからです。

例えば、PythonでSpannerを使うときのコードを覗いてみましょう。

from google.cloud import spanner

クライアントとインスタンス、データベースの準備
client = spanner.Client()
instance = client.instance(“my-instance”)
database = instance.database(“my-database”)

トランザクションの中で実行する処理を定義する関数
def update_stock_and_record(transaction):
# 1. 現在の在庫を読み取る
sql = “SELECT Stock FROM Inventory WHERE ItemID = ‘sneaker_001′”
result = transaction.execute_sql(sql)
current_stock = list(result)[0][0]

if current_stock > 0:
new_stock = current_stock – 1

# 2. 在庫を減らす書き込みを予約する
transaction.execute_update(
“UPDATE Inventory SET Stock = @new_stock WHERE ItemID = ‘sneaker_001′”,
params={“new_stock”: new_stock},
param_types={“new_stock”: spanner.param_types.INT64},
)
print(“在庫の更新準備OKです!”)
else:
raise ValueError(“売り切れです!”)

トランザクションの実行
この runメソッド の中で、裏側でコーディネーターがすべてを管理しています
database.run_in_transaction(update_stock_and_record)

> 💡 先輩エンジニアからのワンポイントアドバイス
>
> 上記のコードにある `database.run_in_transaction()` を呼び出すだけで、Cloud Spannerは自動的にトランザクションマネージャーを立ち上げ、データが保存されているサーバーたちと通信し、先ほど説明した「準備」と「本番」のダンスを華麗に踊ってくれます。
> 私たちはただ「安全に実行したい処理」を関数の中に書くだけでいいのです。なんてエレガントなんでしょう!

—

まとめ:Spannerの優しさに触れて

Cloud Spannerのトランザクションマネージャーは、いわば「絶対に失敗を許されない巨大なオーケストラの指揮者」です。

  • 分散しているサーバーたちの足並みを揃え、
  • 全員の「準備OK」を確認してから一斉に動き出し(2相コミット)、
  • もし1人でも調子が悪ければ、全員を安全な状態に戻す(アボート)。

この仕組みがあるおかげで、私たちは「世界中で同時に何百万人が使ってもデータが壊れない」という圧倒的な安心感を手に入れることができています。

「分散データベースって難しそう……」と思っていたかもしれませんが、裏側で頑張っているコーディネーターの姿をイメージできれば、もう怖くありませんよね。

今日の学びを武器に、ぜひ自信を持ってCloud Spannerの設計や開発に挑んでみてください。あなたのエンジニアリングライフが、もっと楽しく、もっと刺激的になりますように!

コメント

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