0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

妖怪ウォッチの「カセット抜き増殖」から学ぶ分散システム(2)AWS も銀行も50年前の通信も、同じことで悩んでた

0
Last updated at Posted at 2026-11-06

AWS も銀行も50年前の通信も、同じことで悩んでた。電報の機械、昔のコンピュータ、スマホと銀行の間を番号付きの封筒が飛び、470くんが三輪車で通る

🕶️🚲 470(ヨンナナマル)くん
ヨットの帆なのに、陸で三輪車を漕いでいるこのブログの案内役です。今回も、わからないとテルテールがバタバタします。

連載「妖怪ウォッチの『カセット抜き増殖』から学ぶ分散システム」

第1部では、妖怪ウォッチの交換中にカセットを抜くと妖怪が増える話から、こんなことを考えました。

第1部でわかったこと
片方だけ終わる 2台の 3DS はセーブが別々なので、片方だけ書き終わる瞬間がある
消える・増える 先に渡せば消えて、先に受け取れば増える
うまくいかない手 「せーので同時」も「確認し合ってから」も、うまくいかない
おあずけ札 「おあずけ札」を貼ってから送れば、増えない代わりに待たされる

でも、これって妖怪ウォッチだけの悩みなんでしょうか。通信で何かをやり取りしている所なら、どこでも同じことが起きそうじゃないですか。

🤔 これって、妖怪ウォッチだけの悩み?

調べてみたら、やっぱりでした。50年以上前の通信から、今の AWS や銀行まで、みんな同じことで悩んでいました。

この記事でわかること

  • 第1部で出てきた話の、正式な名前
  • 昔の通信、AWS、銀行、PayPay が、同じ問題をどう扱っているか
  • 僕の3つ目の勘違い

銀行や決済サービスの中身は、ほとんど公開されていません。この記事で書くのは、公式ドキュメントや公開資料、障害の報告から分かる範囲だけです。


1. 50年前から、みんな同じことで悩んでた

第1部で、「確認し合っても終わらない」問題には名前がある、と書きました。その名前の前に、昔の人たちがこの問題とどう付き合ってきたかを見てみます。

電報:中身を読み上げて確かめる

アメリカの電報会社 Western Union には、料金を半額分足すと、届いた電報の文面を送った局へ打ち返して、送った文面と突き合わせてもらえるサービスがあったそうです。1919年の裁判の判決に、その約款が引用されています。

妖怪で言うと、交換したあとに相手に「今受け取ったの、このレア妖怪だよね?」と読み上げてもらう感じです。

ただ、これが守っていたのは文字化けみたいな**「中身の間違い」**で、二重に届くのを防ぐものではありません。

1969年:0と1の印で「送り直し」を見分ける

コンピュータ同士を回線でつなぐ研究が進んでいた1969年、イギリスの研究所の3人が、短い論文で面白い方法を出しています。

やること 中身
印を付ける 送るメッセージに、0 か 1 の印を1つだけ付けて、交互に切り替えていく
「受け取ったよ」 相手から返ってくる印が変わったら、それが「受け取ったよ」の意味になる
送り直しを見分ける 前と同じ印のメッセージがまた来たら、それは送り直しだと分かるので、2回目は捨てる

妖怪で言うと、交換のたびにメダルを表、裏、表……と交互にひっくり返して渡す感じです。さっきと同じ向きで来たら「これ、さっきのやつだな」と分かります。

ちなみにこの論文、同じ雑誌の号で「同じ方法を別の人たちも独自に考えていた」と書かれていて、誰が最初とは言い切れないらしいです。

1970年:返事には返事を返さない

インターネットの前身の ARPANET では、データを中継するコンピュータが、次のコンピュータから「受け取ったよ」が来るまでデータを持ち続けて、来なければ 100 ミリ秒くらいで送り直していました1。

面白いのは、論文にはっきり、返事には返事を返さない(Acknowledgments themselves are not acknowledged)と書いてあることです。

第1部で、確認し合うと最後の1通が誰にもわからなくて終わらない、という話をしました。ARPANET はそこに入っていかずに、こうしていました。

  • 返事が来なければ、送り直す
  • 送り直しで2回届いた分は、受け取った側が番号を見て捨てる

確認を終わらせようとするんじゃなくて、送り直しても壊れない形にしていたんです。

1974年〜:番号をもっと大きく

今のインターネットの土台になった TCP の元の論文(1974年)は、送るデータに通し番号を振って、受け取った側がもう受け取った番号を捨てるようにしました。論文には、送り直すなら受け取る側が2回目を見分ける手段が必ず要る、という趣旨のことが書かれています。

そして1975年:確認の往復には名前がついた

第1部の「確認し合っても終わらない」問題は、1975年の通信の設計についての論文に原型があるとされていて、1978年に**「二人の将軍問題」**という名前がついたそうです2。

谷を挟んだ2人の将軍が、使いを走らせて「同時に攻めよう」と約束しようとするけど、使いが捕まるかもしれないので、何往復しても安心できない、という話です。第1部の僕と相手の 3DS と、同じ形ですよね。

年表にすると

年 何が起きた 妖怪で言うと
遅くとも1919 電報の照合(文面を打ち返して確かめる) 受け取った妖怪を読み上げてもらう
1969 0/1 の印で送り直しを見分ける メダルを交互にひっくり返して渡す
1970 返事に返事を返さない、番号で2回目を捨てる 送り直しは気にせず、図鑑の番号で2回目を捨てる
1974 通し番号で、重複・抜け・順番を直す 交換に通し番号を振る
1975・1978(とされる) 二人の将軍問題 第1部の「確認の往復」

1919 電報の照合、1969 0/1の印、1970 返事に返事しない、1974 通し番号、1975 二人の将軍の立て札が並ぶ道を470くんが走る


2. 第1部の話に、名前をつける

ここからは、第1部で妖怪の言葉で話したことに、分散システムの正式な名前をつけていきます。

片方だけ止まる:部分故障

1台の 3DS なら、止まるときは全部いっしょに止まります。2台だと、片方だけ止まることがあります。この「全体のうち一部だけが止まる」ことを、部分故障といいます。分散システムが難しい理由のほとんどは、ここから来ています。

消える側、増える側、ちょうど1回

第1部の2つのパターンにも、近い名前があります。ケンブリッジ大学の Kleppmann という先生の講義ノートでは、送り方を3つに分けています。

名前 やり方 起きうること 第1部で言うと
at-most-once(多くても1回) 返事が来なくても送り直さない 届かずに終わることがある 「先に渡したら消える」(パターン1)に近い側
at-least-once(少なくとも1回) 返事が来るまで送り直す 2回届くことがある 「先に受け取ったら増える」(パターン2)に近い側
exactly-once(ちょうど1回) 送り直しつつ、受け取った側が「これはもう処理した」と見分けて2回目を捨てる ― ―

図にすると、ちょうど1回はこうなります。返事が消えて僕が送り直しても、相手は取引番号を見て2回目を捨てるので、レア妖怪は1体しか増えません。

ここで大事なのは、ちょうど1回というのは「通信がちょうど1回届く」じゃなくて、**「何回届いても、結果が1回分になる」**ということです。

通信をちょうど1回届けるのは無理なので、結果のほうをちょうど1回にしているんですよね。ARPANET や TCP がやっていたのも、これです。

何回やっても1回分:冪等性

第1部でも少し出てきましたけど、「何回やっても、1回やったのと同じ結果になる」性質を、**冪等性(べきとうせい)**といいます。

操作 2回やると 冪等?
妖怪図鑑に「レア妖怪を見つけた」と登録する 何回やっても、図鑑は1つ埋まるだけ ⭕ 冪等
手持ちに妖怪を1体増やす 2回やったら2体増える ❌ 冪等じゃない

交換を冪等にするには、「この取引番号の交換は、もう終わってるか」を覚えておいて、2回目なら何もしないようにします。第1部のおあずけ札の取引番号は、このためのものでした。

返事が来ないのは、止まったから? 遅いから?:僕の勘違い③

第1部で、僕の勘違いを2つ紹介しました(光の速さと時計のズレ)。実はもう1つあります。

調べ始めたころ、僕は「FLP 不可能性定理(1985年)によると、1台でも止まる可能性があるなら、100%確実に合意する方法は数学的に存在しない」と理解していました。だから、カセット抜きは数学の限界を突く行為なんだ、と。

これも、半分違いました。

FLP 不可能性定理が言っているのは、「相手が止まったのか、ただ遅いだけなのかを見分ける手段がまったくない世界では、いつか必ず結論を出す、とは保証できない」ということです。

妖怪で言うと、返事が来ない相手が、カセットを抜かれたのか、通信が遅いだけなのか、僕の 3DS には見分けられない。だから「いつまで待てば必ず決着がつく」とは言えない、という話です。

でも、データが食い違わないこと(正しさ)まで諦めろ、とは言っていません。 今よく使われている Raft という合意のやり方の論文には、正しさは時間に頼ってはいけない(safety must not depend on timing)とはっきり書かれています。タイムアウトは、話を先に進めるためだけに使う。

僕が最初に思ってた 実は
FLP 不可能性定理 100%確実に合意する方法は数学的に存在しない 「いつか必ず結論を出す」とは保証できない。正しさは守れる

諦めるのは正しさじゃなくて、「必ず終わること」のほうだったんです。

第1部のおあずけ札が「増えない代わりに待たされる」だったのも、まさにこれでした。

幹事を立てても、幹事が倒れたら止まる:2相コミット

「2台で決めるからダメなんでしょ? 3台目の幹事役を立てればいいじゃん」という方法もあります。2相コミットといって、データベースでは昔からある方法です。

  1. 幹事が2人に「交換の準備できた?」と聞く
  2. 2人とも「できたよ」と答えたら、幹事が「じゃあ確定して」と号令をかける

ここで、2人が「できたよ」と答えた直後に、幹事の 3DS のカセットが抜かれたらどうなるか。

2人は、自分だけで「確定する」「やめる」を決められません。勝手に決めたら、もう1人と食い違うかもしれないからです。なので、幹事が戻ってくるまで待ち続けます。

ここでよく誤解されるんですけど、2相コミットは幹事が倒れても、データが食い違うわけじゃありません。止まって待たされる。 これも、正しさを守る代わりに待たされる、という形です。

カセット抜きは「故障」じゃなくて「ズル」

最後に、大事な区別をしておきます。故障にはいくつか種類があります。

故障の種類 どうなる?
止まったら、それっきり ―
止まるけど、あとで戻ってくる セーブは残っている
決まりどおりに動かない 嘘をついたり、わざと変なことをしたりする

カセット抜き自体は、止まる故障を人がわざと起こしている形です。でも、遊んでいる人はその気になれば、第3部で出てくるセーブの書き戻しみたいな、3つ目のズルもできてしまいます。

ネットのゲームの作り方を解説した有名な記事には、「プレイヤーはズルをしようとする、と最悪を想定しておけ」「ゲームの状態はサーバーだけが管理する」と書かれています。通信を信用しないだけじゃなくて、相手の端末も信用しない、ということです。


3. 実務①:AWS は「2通届く前提」で作る

ここからは、実際のシステムがどうしているかを見ていきます。まずは AWS の公式ドキュメントです。

この章のコードは、AWS 公式の Python ライブラリ(boto3)で書いたものです。本物の AWS にはつながずに、moto(AWS の偽物を PC の中で動かす道具)に向けて実際に動かしました。moto が真似していない所(時間の期限など)は、AWS の公式ドキュメントに書いてあることとして分けて書いています。

AWS の資料を読んで分かったのは、どこにも「絶対に重複しない」とは書いていなくて、**重複を捨てるのはいつも「決まった時間の間だけ」「決まった条件のときだけ」**だということでした。

やり直しは、1か所で、間を空けて、ずらす

交換に失敗したとき、僕も相手も相手の兄弟も、全員で一斉に「もう1回!」と連打したらどうなるか。

AWS の資料には、5段の仕組みがそれぞれ3回ずつやり直すと、一番奥のデータベースには 243 倍の負荷がかかる、という例が出てきます(3×3×3×3×3)。

なので AWS は、やり直すのは1か所だけにして、やり直すたびに待ち時間を伸ばして、さらに待ち時間を少しずつランダムにずらすよう勧めています。全員が同じ瞬間にやり直さないようにするためです。

「まだ手元にいるときだけ渡す」「全部か、何もしないか」

AWS のデータベース(DynamoDB)には、こんな書き方があります。

書き方 妖怪で言うと 注意
条件付きで書く 「このレア妖怪がまだ僕の手元にいるときだけ渡す」。2回目は、もういないので失敗する ―
まとめて書く 「僕から消す」と「相手に足す」を1つにまとめて、両方成功するか、両方やめるか 最大 100 件まで
整理番号 同じ番号で何回送っても1回分の結果になる 番号が効くのは、最初の依頼が終わってから 10 分だけ

「まだ僕の手元にいるときだけ渡す」は、コードにするとこうなります。

boto3(DynamoDB の条件付き書き込み)
ddb.update_item(
    TableName="Yokai",
    Key={"yokai_id": {"S": "rare-0721"}},           # どの妖怪の行か
    UpdateExpression="SET #o = :to",                # 持ち主を B に書き換える
    ConditionExpression="#o = :from",               # ただし、今の持ち主が A のときだけ
    ExpressionAttributeNames={"#o": "owner"},
    ExpressionAttributeValues={":from": {"S": "A"}, ":to": {"S": "B"}},
    …
)
  • UpdateExpression が「どう書き換えるか」、ConditionExpression が「どんなときだけ書き換えるか」です。
  • 条件を確かめるのと書き換えるのを、DynamoDB が一度にやってくれます。なので、「確かめた」と「書いた」の間に、ほかの頼みが割り込むことはありません。
  • #o や :from は、あとから名前や値を差し込むための空欄です。{"S": "A"} の S は「文字列」という意味です。

moto で動かしてみると、1回目は成功して、同じことをもう一度頼むと ConditionalCheckFailedException(条件に合わなかった)というエラーになりました。2回目は、もう持ち主が B だからです。

「僕から消す」と「相手に足す」をまとめるほうは、こうです。

boto3(DynamoDB の TransactWriteItems・抜粋)
ddb.transact_write_items(
    ClientRequestToken="trade-No.0721",   # 整理番号
    TransactItems=[
        {"Update": {…僕の手持ちを -1。ただし 1体以上あるときだけ…}},
        {"Update": {…相手の手持ちを +1…}},
    ],
)

2つの書き換えを、両方やるか、両方やめるかにします。ClientRequestToken が整理番号で、公式ドキュメントでは「同じ番号なら、10 分の間は2回目を書かない」とされています。

moto はこの整理番号の動きを真似していなくて、同じ番号で2回頼むと、もう一度実行しようとしました(条件に合わず失敗)。なので、整理番号の効き目は、僕は動かして確かめられていません。10 分の話は公式ドキュメントの記述です。

手紙は2通届く前提で、受け取る側が見分ける

AWS のメッセージを受け渡すキュー(SQS)は、普通のものだと同じメッセージが2回届くことがあって、AWS 自身が「受け取る側を冪等に作ってね」と書いています。順番を守るタイプ(FIFO)は同じ番号のメッセージを捨ててくれますが、それも 5 分の間だけです。

FIFO で同じものを捨ててもらうには、送るときに番号を付けます。

boto3(SQS の FIFO キュー)
sqs.send_message(QueueUrl=fifo, MessageBody="GIVE レア妖怪 No.0721",
                 MessageGroupId="player-A",               # 同じグループの中は順番どおり
                 MessageDeduplicationId="trade-No.0721")  # 同じ番号の手紙は1通にまとめる

moto で、普通のキューに同じ手紙を2回出すと2通届いて、FIFO に同じ番号で2回出すと1通だけ届きました。ただ、普通のキューの「1回しか出していないのに2回届く」は、AWS の中でコピーが何台ものサーバーに置かれることから起きるもので、moto では再現できません。5 分の期限も、moto では確かめていません。

受け取る側に「処理済みノート」を持たせる道具(Powertools)もあって、標準だと記録は 1 時間で消えます。1回目の処理が終わる前に同じものが来たら、「今やってるところ」というエラーを返します。

Powertools は、関数の上に札を1枚付けるだけで使えます。

Powertools for AWS Lambda(Python)
@idempotent_function(data_keyword_argument="trade", persistence_store=store, config=config)
def give(trade):
    …  # 交換の処理

store は「ノートをどこに置くか」で、今回は DynamoDB にしました。config では「取引番号のところを見て、同じ依頼か決めてね」「同じ番号なのに妖怪が違ったらエラーにしてね」の2つを指定しています。moto で動かすと、同じ取引番号で2回呼んでも中身は1回しか動かず、2回目は1回目の結果が返ってきました。同じ番号で妖怪を変えるとエラー(2つ目の指定のおかげ)に、1回目の途中で同じ依頼が来ても「今やってるところ」のエラーになりました。

仕組み 重複を捨ててくれる時間
DynamoDB の整理番号 10 分
SQS の FIFO 5 分
Powertools の処理済みノート 1 時間(標準)

途中で失敗したら、逆順に取り消す

AWS が公式に紹介しているやり方に、Saga があります。

順方向 注文 → 在庫を減らす → 支払い
途中で失敗したら(逆順に取り消す) 支払いの取り消し → 在庫を戻す → 注文の削除

ただ、取り消しが終わるまでの間、途中の状態が他の人から見えてしまうので、AWS は**「処理中」の印**を付けるよう勧めています。これ、第1部のおあずけ札とほぼ同じ考え方ですよね。

なお、Amazon 自身が「うちの注文はこう作っている」と説明した公式資料は見つからなかったので、ここに書いたのは「AWS が勧めている作り方」です。


4. 実務②:銀行は「お知らせ」と「精算」を分ける

次は銀行です。こっちは中身がほとんど公開されていないので、公開資料と障害の報告から分かる範囲で書きます。

振込は、2本の道でできている

日本の銀行同士の振込は、全銀システムという仕組みが中継しています。1973年から動いていて、1日に約 843 万件を扱っているそうです(2025年12月時点)。

面白いのは、振込が2本の道でできていることです。

道 中身
お知らせの道 「A銀行のこの口座から、B銀行のこの口座へ」という電文を、全銀センターが中継する
お金の精算の道 銀行同士のお金の受け渡しは、日本銀行にある各銀行の口座で行う。1件1億円以上は1件ずつその場で、1億円未満は「払った分と受け取った分の差」だけを、毎日 16 時 15 分にまとめて精算する

妖怪で言うと、交換の「渡したよ」のお知らせを先に届けて、メダルの実物の受け渡しは放課後にまとめてやる感じです。払いすぎないように、銀行ごとに上限額と担保(あずけておくお金)も決まっています。

A銀行とB銀行の間で、上の道をお知らせの封筒が速く走り、下の道をお金の袋がゆっくり運ばれている

二重に送らない仕組みは、公開されていない

全銀システムが同じ電文をどう見分けているかは、公開資料には書かれていませんでした。

ただ、手がかりはあります。2023年10月に全銀システムで大きな障害が起きたあと、運営している全銀ネットは、再発防止策の1つとして**「送り漏れと二重発信を確かめる訓練」**を新しく行う予定だと報じられています。動かしている側も、緊急時には「漏れ」と「二重」の両方が起きうると見ているのかもしれません。

利用者側のルールにも、同じ考え方が出てきます。セブン銀行のネット取引の規定には、「返事が決まった時間内に来なければ取り消し扱い。成功したかどうかは明細で確かめて」と書いてあります。

分からなければ取り消す。でも、取り消しも失敗する

ATM で、引き出しの途中に通信が切れたらどうするか。カード決済の国際規格では、結果が分からない取引は取り消しのお知らせを送って元に戻す、とされています3。インドの中央銀行は、「お金が引き落とされたのに現金が出なかった」ときは5日以内に自動で戻すよう決めていて、遅れたら1日 100 ルピーを銀行がお客さんに払うそうです。

でも、取り消しも失敗することがあります。 2021年2月のみずほ銀行の障害では、カードや通帳が ATM に取り込まれ、取り消しの処理まで失敗したそうです。取り込まれたのは 5,244 件と報じられています。

銀行で起きた「パターン2」

一番第1部に近いのが、2011年3月のみずほ銀行の障害です。振込が処理されずにたまってしまい、入金漏れを怖がって、自動処理と手作業の両方で入金した結果、「念のための二重入金」が約 1000 件起きたと報道されています。

消えるのが怖くて、増えるほうを選んでしまう。 第1部のパターン2(先に受け取る側)と似た形が、銀行でも起きていました。

海外の送金は「重複かも」の印を付けるだけ

国際送金の SWIFT には、送り直すときに**「これ、さっきのと同じかも」という印**を付ける仕組みがあります。でも、本当に重複かを判断するのは受け取った側で、自動で消してくれるわけではないそうです。


5. 実務③:PayPay と Stripe は「お店の番号」で見分ける

最後に、決済サービスです。

PayPay のお店向けの仕組みでは、お店が支払いごとに merchantPaymentId という番号を付けます。同じ番号でもう一度送られてきたら、PayPay は前回の結果を返すだけで、2回目の支払いはしません。

ただし、時間切れで返事が来なかったときは、「結果は不明」として扱って、状態を問い合わせるよう求めています。送り直す前に「今どうなってる?」を確かめる、ということです。

アメリカの決済サービス Stripe も、同じ考え方で Idempotency-Key という番号を使っています。番号は少なくとも 24 時間覚えていて、同じ番号の依頼がまだ処理中なのにもう一度来たら、「まだ処理中」というエラーを返します。

この Idempotency-Key は、ネットの標準を決める IETF で規格にしようとしている途中で、2026年10月時点でもまだ草案です。PayPay はこのヘッダーではなく、お店が付ける番号で見分けています。

何で見分ける? 覚えている期間など
PayPay お店が付ける番号(merchantPaymentId) 返事が来なければ、まず状態を問い合わせる
Stripe Idempotency-Key 少なくとも 24 時間。処理中の重複はエラー
IETF の規格 Idempotency-Key ヘッダー 2026年10月時点で草案

Stripe の公式ライブラリで書くと、番号はこう付けます。

stripe-python
client.v1.payment_intents.create(
    params={"amount": 500, "currency": "jpy"},        # 500円の支払い
    options={"idempotency_key": "trade-No.0721"},     # 整理番号
)

本物の Stripe にはつながずに、PC の中に立てた偽のサーバーへ向けて動かしてみました。偽のサーバーは、1本目の頼みにだけわざと返事をしません。ライブラリには「通信に失敗したら2回まで自分で送り直して」(max_network_retries=2)と設定しています。

試したこと 送られてきた Idempotency-Key
番号を自分で付けた 最初の1本も、送り直しの1本も trade-No.0721
番号を付けなかった ライブラリが自分で番号を作り、最初の1本と送り直しの1本で同じ番号

ライブラリが自分で作る番号は、その1回の頼みの中だけのものだと考えられます(コードを読んでの推論で、試してはいません)。アプリが落ちて起動し直したら、もう覚えていない。だから本当に守りたいなら、取引番号から番号を作って、自分でセーブしておくのが良さそうです。第1部のおあずけ札で、取引番号をカセットにセーブしていたのと同じですよね。24 時間覚えている、処理中ならエラー、の2つは偽のサーバーでは確かめられないので、公式ドキュメントの記述です。

1969年の 0/1 の印が、今は**「お店が付ける番号」や「24 時間覚えておく番号」**になっているわけです。


6. 話し合わなくても合体できるもの、できないもの

最後に、ちょっと違う方向の話です。

Notion や Figma みたいなアプリは、オフラインで編集しても、あとでつないだら合体してくれますよね。前に僕も「なんで Notion や Figma はオフラインで動くのに、交換はダメなの?」って疑問に思ったことがありました。

分けて考えると、こうなります。

例 なぜ?
⭕ 合体できるもの メモに文章を書き足す、図鑑に見つけた妖怪を登録する こういう「増える一方」のものは、各自が勝手にやっても、あとで足し合わせれば同じ結果になります
❌ 合体できないもの 「世界に1体しかいないレア妖怪を渡す」「残高をマイナスにしない」 こういうものは、他の誰かが同じことをしていないかを確かめないと、正しく判断できません

これには理論の裏付けもあって、カリフォルニア大学バークレー校の研究者たちが、**「話し合い(協調)なしで正しく合体できるのは、増える一方の処理だけ」**という定理(CALM 定理)を示しています。別の研究では、「残高を0以上に保ったまま減らす」ような処理は、話し合いなしでは守れない、と整理されています。

ちなみに、Notion や Figma が実際に何を使っているかも調べてみました。

アプリ 方式
Figma 本物の CRDT(勝手に編集しても合体できるデータの作り方)ではなく、サーバーが最終的に決める方式だと、Figma 自身が書いています
Notion オフライン用に指定したページだけ、CRDT に切り替えるそうです
Google ドキュメント 2010年の公式ブログでは、OT という別の方式だと書かれていました4

定理が例に挙げているのは残高や「同じ番号は1つだけ」のような話ですけど、世界に1体のレア妖怪を渡すのも同じ形だと考えられます。ということは、**レア妖怪の交換は「話し合いが要る側」**なので、オフラインで勝手にやって、あとで合体、はできない。第1部のおあずけ札が、最後に必ず相手と答え合わせしていたのは、そのためでした。


まとめ

第2部のまとめ

  • 第1部の話には名前がある。片方だけ止まる=部分故障、先に渡して消える=at-most-once、先に受け取って増える=at-least-once、確認の往復=二人の将軍問題。
  • ちょうど1回は、通信を1回にするのではなく、送り直し+番号で2回目を捨てて「結果を1回分」にすること(冪等性)。50年前の通信から、今の AWS・PayPay・Stripe まで同じ形。
  • FLP 不可能性定理が諦めさせるのは正しさではなく、「必ず終わること」。2相コミットも、幹事が倒れたら食い違うのではなく止まる。
  • 銀行は、お知らせと精算を分け、分からなければ取り消し、あとで突き合わせる。それでも障害時には二重も漏れも起きている。
  • 「世界に1体」や「残高」は、話し合いなしには守れない。だから最後に答え合わせが要る。

僕の学び

大きなインフラであっても、根本的な問題として、システムは必ず障害を起こしちゃう。なので、いつかそれを完璧に対策する、っていうのは難しいんだなぁと思いました。

特に、札を付けたり中央サーバーを用意したりしても、どれかが崩れるかもしれない。それに、毎日、毎分、毎秒、大量の処理をしているということは、それなりにやっぱり障害も起きちゃうんですよね。インフラって大変だなぁと思いました。

ちなみに僕はみずほ銀行じゃなかったので、障害は受けなかったです。障害を受けてお金が増えていればよかったなぁ(笑)。

これで、妖怪ウォッチ以外の実際の現場でどうしているかは、語れたかなと思います。

🕶️🚲 テルテール、ピシッと風に乗りました。

次は、僕が実際に妖怪ウォッチを今作り替えるならこうする、というのを第3部で紹介したいと思います。ぜひ見ていてください。


連載「妖怪ウォッチの『カセット抜き増殖』から学ぶ分散システム」

参考にした資料(クリックで開く)

通信の歴史

理論

AWS

銀行

動かしたライブラリ(実行は PC の中だけ)

  • boto3 1.42.97、moto 5.1.22、aws_lambda_powertools 3.23.0、stripe 16.1.0(Python 3.14.10)

決済・同時編集

  1. 1970年時点の設計です。 ↩

  2. どちらも、僕は原文を読めていません。由来は二次資料によります。 ↩

  3. 僕は二次資料でしか確認できていません。 ↩

  4. 今もそうかは確認できていません。 ↩

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?