こんにちは!Cloud Spannerの世界へようこそ。
チーフアーキテクトの私です。
今日は、Cloud Spannerという世界最高峰のデータベースが裏側でやっている、ちょっとスリリングで、しかしものすごく洗練された仕組み「分散デッドロック検出」についてお話しします。
「分散トランザクション? デッドロック?」
なんだか難しそうな漢字が並んで身構えてしまうかもしれませんが、大丈夫。ここをクリアすれば、Cloud Spannerの基本はバッチリマスターできますよ。
それでは、コーヒー片手にリラックスして、私たちの日常の「あるある」から紐解いていきましょう。
—
1. カフェのレジ待ちで起きる「睨めっこ(デッドロック)」
まずは、データベースの難しい話はちょっと置いておいて、身近な例えから始めましょう。
想像してください。とある人気カフェで、レジの行列に並んでいます。
- あなたは、どうしても欲しかった「限定タンブラー」と「最後の1個のケーキ」をトレーに乗せています。
- あなたの前にいるAさんも、「限定タンブラー」と「最後の1個のケーキ」を狙っています。
ここで、こんな状況が起きました。
1. あなたは「ケーキ」の確保をレジの人にお願いしました(ロック取得)。
2. Aさんは「タンブラー」の確保を別のレジの人にお願いしました(ロック取得)。
3. その後、あなたはAさんが持っている「タンブラー」が欲しくなり、「それを譲ってよ」とAさんに声をかけました。
4. 同時に、Aさんもあなたが持っている「ケーキ」が欲しくなり、「それを譲ってよ」とあなたに声をかけました。
さあ、どうなるでしょう?
あなたはAさんがタンブラーを離すのを待ち、Aさんはあなたがケーキを離すのを待つ。お互いに相手が手放すのを永遠に待ち続ける状態になってしまいました。これが、コンピュータの世界でいう「デッドロック(膠着状態)」です。
2. Cloud Spannerの「分散環境」という広大な世界
これが1台のパソコン(コンピュータ)の中だけで起きるなら、管理するのは簡単です。でも、Cloud Spannerは違います。
Cloud Spannerは、世界中にデータをちらばらせて、何台もの強力なサーバー(ノード)がチームを組んで動く「分散データベース」です。
つまり、先ほどの例えで言えば、
- 「ケーキ」の担当サーバーは東京にあり、
- 「タンブラー」の担当サーバーはアメリカのオハイオにある、
……なんてことが日常茶飯事なのです。
別々の国、別々のサーバーにいる人たちが、お互いのリソースを欲しがって「通行止め」を起こしているとき、誰が全体を見渡して「おいおい、これじゃ永遠に進まないから、一度仕切り直そう!」と交通整理するのでしょうか?
これが、今回のお題である「分散デッドロック検出」の仕事です。
—
3. スパナくんの「待ち合わせの相関図(待機グラフ)」
Cloud Spannerのエンジンルームでは、目に見えない「交通整理員(ここではスパナくんと呼びましょう)」が常に働いています。
スパナくんは、トランザクション(一連の処理のまとまり)たちが「誰の何を待っているのか」を、まるでSNSの人間関係の相関図のようにメモしていきます。これを専門用語で「待機グラフ(Wait-for Graph)」と呼びます。
- トランザクションA ➔ 「トランザクションBのデータを待っています」
- トランザクションB ➔ 「トランザクションCのデータを待っています」
- トランザクションC ➔ 「……おや? トランザクションAのデータを待っているぞ?」
スパナくんは、この相関図の中に「環っか(ループ=循環待ち)」を見つけた瞬間、鋭い目を光らせます。
「おっと、ここでぐるぐる回っているぞ! このままだと永遠に終わらない!」
—
4. どうやって解決するの?(タイムアウトと仕切り直し)
循環待ちを見つけた、あるいは「ちょっと待ち時間が長すぎやしないか?」とスパナくんが判断したとき、彼は非常に冷徹かつ慈悲深い決断を下します。
それは、「どちらか一方のトランザクションを強制的に失敗させ、やり直させる(アボートする)」という方法です。
カフェの例えに戻りましょう。
スパナくんが「あなたとAさんは永遠に待ち合っていますね。では、あなた、一度列から離れて最初から並び直してください!」と強制的に交通整理をするわけです。
あなたが列を離れたことで、Aさんは無事にケーキとタンブラーを手に入れ、買い物を終えることができます。あなたは少しイラッとするかもしれませんが、店全体がフリーズしてしまう最悪の事態(システム全体の停止)を防ぐことができるのです。
Cloud Spannerでは、この「待ちぼうけ」の限界時間をあらかじめ決めておき、その時間を過ぎたり、きれいにループを検知したりすると、自動的にどれか一つの処理をキャンセルしてエラーを返します。
アプリケーションを作る側(私たちエンジニア)は、このエラーを受け取ったときに「あ、デッドロックで一度弾かれたんだな。じゃあ、もう一回はじめからやり直そう(リトライしよう)」という優しい設計をコードに仕込んでおくことが、実務における極意となります。
—
まとめ:恐るるに足らず、Spannerはすべてを知っている
いかがでしたか?
- デッドロックとは:お互い譲らずに待ちぼうけになってしまうこと。
- 分散環境での難しさ:別々のサーバーに散らばった状態でも、誰かが全体を見渡して見つけ出さなきゃいけないこと。
- 解決策:スパナくんが「待機グラフ」でループを見つけ、片方を優しく(強制的に)リトライさせること。
Cloud Spannerは、私たちが意識しなくても、この複雑な分散デッドロックの検知と解消を裏側で完璧にこなしてくれています。だからこそ、私たちは安心して巨大なシステムを任せることができるのです。
ここを理解できれば、Cloud Spannerのトランザクションが持つ「力強さと優しさ」の本質が見えてきます。
さあ、自信を持って次のステップへ進みましょう!
コメント