Slide 1

Slide 1 text

#devsumi #devsumiF #devsumi #devsumiF 「厳密な共通言語」としての 形式手法 チェシャ猫 (@y_taka_23) Developers Summit 2020 [F-13-6] (2020/02/13)

Slide 2

Slide 2 text

#devsumi #devsumiF #devsumi #devsumiF 本日のアジェンダ ● システムの仕様と曖昧性 ● 形式手法とツールの概要 ● モデリングを通した仕様の明確化 ● 環境と相互作用する複雑な挙動の解析

Slide 3

Slide 3 text

#devsumi #devsumiF #devsumi #devsumiF 1. 仕様に隠された曖昧性 Ambiguities in the Specification

Slide 4

Slide 4 text

#devsumi #devsumiF 例:チェスのルール改定 参考文献:https://old.fide.com/fide/handbook.html?id=208&view=article

Slide 5

Slide 5 text

#devsumi #devsumiF ポーンは最前列に到達した際 クイーン・ビショップ・ルーク・ナイト のいずれかに成ることができる

Slide 6

Slide 6 text

#devsumi #devsumiF ポーンは最前列に到達した際 クイーン・ビショップ・ルーク・ナイト のいずれかに成らねばならない

Slide 7

Slide 7 text

#devsumi #devsumiF ポーンは最前列に到達した際 同色のクイーン・ビショップ・ルーク・ナイト のいずれかに成らねばならない

Slide 8

Slide 8 text

#devsumi #devsumiF 例:最大値関数

Slide 9

Slide 9 text

#devsumi #devsumiF max(x, y): x と y のうち大きい方を返す

Slide 10

Slide 10 text

#devsumi #devsumiF max(x, y): x と y のうち小さくない方を返す

Slide 11

Slide 11 text

#devsumi #devsumiF 例:水位上昇によるポンプの遮断 参考文献:https://www.researchgate.net/publication/242413466_Assessment_of_safety-critical_software_in_nuclear_power_plants

Slide 12

Slide 12 text

#devsumi #devsumiF 水位が 4 秒以上、100m を上回ったら ポンプを遮断する

Slide 13

Slide 13 text

#devsumi #devsumiF 過去 4 秒間の水位の最小値が 100m を上回ったらポンプを遮断する

Slide 14

Slide 14 text

#devsumi #devsumiF 過去 4 秒間の水位の二乗平均平方根が 100m を上回ったらポンプを遮断する

Slide 15

Slide 15 text

#devsumi #devsumiF #devsumi #devsumiF 曖昧さはイメージの限界から生まれる ● 仕様を理解した「つもり」の思い込み ○ ポーンが成るなら当然、同色の駒である ○ 比較可能な値なら当然、大きい方が取れる ○ 基準値を上回るかどうかなら当然、最小値を見ればよい ● 最初に思いついたもの以外は見落としがち ○ 指摘されるまでは見落としていること自体気づかない

Slide 16

Slide 16 text

#devsumi #devsumiF 単なる「言葉遊び」に見える?

Slide 17

Slide 17 text

#devsumi #devsumiF 例:統合決済基盤

Slide 18

Slide 18 text

#devsumi #devsumiF #devsumi #devsumiF とある決済サービスの仕様 ● システム横断的な決済基盤 ○ 複数の EC サイトから利用される ● 複数の決済手段をサポート ○ 銀行引き落とし / ポイント払い / ギフト券払い ○ 各々が別々のマイクロサービスとして稼働 ○ 複数の手段に按分して支払うことも可能

Slide 19

Slide 19 text

#devsumi #devsumiF ポイント管理 1000 pt ギフト券管理 1000 円 銀行口座管理 1000 円 決済サービス

Slide 20

Slide 20 text

#devsumi #devsumiF ポイント管理 1000 pt ギフト券管理 1000 円 銀行口座管理 1000 円 決済サービス 1000 円支払

Slide 21

Slide 21 text

#devsumi #devsumiF ポイント管理 1000 pt ギフト券管理 1000 円 銀行口座管理 1000 円 決済サービス 1000 円支払 - 500 円 - 500 pt

Slide 22

Slide 22 text

#devsumi #devsumiF ポイント管理 500 pt ギフト券管理 1000 円 銀行口座管理 500 円 決済サービス 1000 円支払

Slide 23

Slide 23 text

#devsumi #devsumiF ポイント管理 500 pt ギフト券管理 1000 円 銀行口座管理 500 円 決済サービス 1000 円支払 OK OK

Slide 24

Slide 24 text

#devsumi #devsumiF ポイント管理 500 pt ギフト券管理 1000 円 銀行口座管理 500 円 決済サービス OK

Slide 25

Slide 25 text

#devsumi #devsumiF 処理中にエラーが発生した場合

Slide 26

Slide 26 text

#devsumi #devsumiF ポイント管理 1000 pt ギフト券管理 1000 円 銀行口座管理 500 円 決済サービス 1000 円支払 OK ERROR

Slide 27

Slide 27 text

#devsumi #devsumiF ポイント管理 1000 pt ギフト券管理 1000 円 銀行口座管理 500 円 決済サービス OK or Retry?

Slide 28

Slide 28 text

#devsumi #devsumiF #devsumi #devsumiF TCC パターン ● 全体を二つのフェイズに分割する ● Try フェイズ ○ 各メンバーに更新内容を仮登録させる ● Confirm / Cancel フェイズ ○ 全員から準備 OK が返って来たら改めて Confirm ○ 一人でも失敗した場合には全員に Cancel させる

Slide 29

Slide 29 text

#devsumi #devsumiF ポイント管理 ギフト券管理 銀行口座管理 決済サービス Try

Slide 30

Slide 30 text

#devsumi #devsumiF ポイント管理 ギフト券管理 銀行口座管理 Reserved 決済サービス Try OK

Slide 31

Slide 31 text

#devsumi #devsumiF ポイント管理 Reserved ギフト券管理 銀行口座管理 Reserved 決済サービス Try OK

Slide 32

Slide 32 text

#devsumi #devsumiF ポイント管理 Reserved ギフト券管理 銀行口座管理 Reserved 決済サービス Confirm

Slide 33

Slide 33 text

#devsumi #devsumiF ポイント管理 Confirmed ギフト券管理 銀行口座管理 Reserved 決済サービス Confirm OK

Slide 34

Slide 34 text

#devsumi #devsumiF ポイント管理 Confirmed ギフト券管理 銀行口座管理 Confirmed 決済サービス Confirm OK

Slide 35

Slide 35 text

#devsumi #devsumiF 処理中にエラーが発生した場合

Slide 36

Slide 36 text

#devsumi #devsumiF ポイント管理 Error ギフト券管理 銀行口座管理 Reserved 決済サービス Try Error

Slide 37

Slide 37 text

#devsumi #devsumiF ポイント管理 Error ギフト券管理 銀行口座管理 Reserved 決済サービス Cancel

Slide 38

Slide 38 text

#devsumi #devsumiF ポイント管理 Canceled ギフト券管理 銀行口座管理 Canceled 決済サービス Cancel

Slide 39

Slide 39 text

#devsumi #devsumiF 本当に「理解」してますか?

Slide 40

Slide 40 text

#devsumi #devsumiF #devsumi #devsumiF TCC パターンの「曖昧」な部分 ● 未定義動作のないシステムの正確な挙動 ○ 各コンポーネントの動作と、非同期に動いた系全体の挙動 ● 保証したい仕様の意味 ○ 不整合とは何か、どういう状況なら許容できるのか ● アルゴリズム外の環境との相互作用 ○ 動作している各サーバの信頼性、ネットワークの状態

Slide 41

Slide 41 text

#devsumi #devsumiF #devsumi #devsumiF 分散コンピューティングの落とし穴 ● ネットワークは信頼できる ● レイテンシはゼロである ● 帯域幅は無限である ● ネットワークはセキュアである ● ネットワークトポロジは不変である ● 管理者は一人である ● トランスポートコストはゼロである ● ネットワークは均質である 参考文献:https://web.archive.org/web/20171107014323/https://blog.fogcreek.com/eight-fallacies-of-distributed-computing-tech-talk/

Slide 42

Slide 42 text

#devsumi #devsumiF #devsumi #devsumiF 分散コンピューティングの落とし穴 ● ネットワークは信頼できる ● レイテンシはゼロである ● 帯域幅は無限である ● ネットワークはセキュアである ● ネットワークトポロジは不変である ● 管理者は一人である ● トランスポートコストはゼロである ● ネットワークは均質である イメージの限界による曖昧さの発生 参考文献:https://web.archive.org/web/20171107014323/https://blog.fogcreek.com/eight-fallacies-of-distributed-computing-tech-talk/

Slide 43

Slide 43 text

#devsumi #devsumiF #devsumi #devsumiF 曖昧性ハンドリングの重要性 ● アーキテクチャの大規模・複雑化 ○ マイクロサービス間の疎結合性 ○ チーム間での仕様や制約の合意のコスト ○ マネージドインフラにおける変えられない前提条件 ● 開発環境やチーム構成の多様化 ○ 均質な前提知識やイメージを期待できない

Slide 44

Slide 44 text

#devsumi #devsumiF テストでカバーすべき?

Slide 45

Slide 45 text

#devsumi #devsumiF #devsumi #devsumiF テストでカバーできない点 ● テストケースの網羅性・再現性 ○ テストケースとして明示的に思いつく必要がある ○ 非同期性による実行パスのランダム性 ● 実装が先行する必要性 ○ 実際にテスト対象となるシステムの実装が必要 ○ 暗黙の仮定を仕様バグとして作り込んでしまうと手戻り

Slide 46

Slide 46 text

#devsumi #devsumiF 複雑さを扱いうる「言葉」の必要性

Slide 47

Slide 47 text

#devsumi #devsumiF #devsumi #devsumiF 第 1 章のまとめ ● 仕様を厳密に表現するのは意外と難しい ○ イメージできる範囲の挙動に引きずられる ○ 知識や前提が共有されている必要がある ● 実システムの挙動は大量の曖昧さを含む ○ テストは曖昧さを排除する方法の一つだが万能ではない ○ システムの性質をより正確に記述できる方法論が欲しい

Slide 48

Slide 48 text

#devsumi #devsumiF 何であれば「共通言語」足り得るのか

Slide 49

Slide 49 text

#devsumi #devsumiF #devsumi #devsumiF 形式手法 Formal Methods

Slide 50

Slide 50 text

#devsumi #devsumiF #devsumi #devsumiF 2. はじめての形式手法 Hello, Formal Methods!

Slide 51

Slide 51 text

#devsumi #devsumiF #devsumi #devsumiF 形式手法とは ● システムを数学的対象により表現 ○ その対象の性質に基づいて検証を行う ○ 対象として何を選ぶかによってツールの性質が決まる ● テストに対する優位点 ○ テストケースの抜けや漏れが生じない ○ 実装ではなく仕様や設計に対して検査ができる

Slide 52

Slide 52 text

#devsumi #devsumiF #devsumi #devsumiF 形式手法の分類 ● モデル検査 ○ システムが取りうる状態を列挙して探索 ○ 有限個の探索に帰着できる範囲で自動化が可能 ● 定理証明 ○ いわゆる数学的な証明をプログラムとして表現 ○ 本当に無限個のパターンがある対象を扱える

Slide 53

Slide 53 text

#devsumi #devsumiF

Slide 54

Slide 54 text

#devsumi #devsumiF #devsumi #devsumiF TLA+ の特徴 ● モデル検査系のツール ○ Eclipse ベースの IDE(TLA Toolbox)とセットで提供 ○ Lamport(Paxos の発案者)が中心となって開発 ○ Temporal Logic of Actions と呼ばれる論理がベース ● システムを状態の列として表現 ○ 起こり得る動作の前後で成り立つ関係を記述

Slide 55

Slide 55 text

#devsumi #devsumiF よくある「学者のオモチャ」なのでは?

Slide 56

Slide 56 text

#devsumi #devsumiF #devsumi #devsumiF TLA+ の採用事例 ● AWS DynamoDB、S3 ○ https://lamport.azurewebsites.net/tla/formal-methods-amazon.pdf ● CockroachDB の並列コミット ○ https://www.cockroachlabs.com/blog/parallel-commits/ ● FINAL FANTASY XV POCKET EDITION ○ https://d1.awsstatic.com/events/jp/2018/summit/tokyo/customer/37.pdf

Slide 57

Slide 57 text

#devsumi #devsumiF #devsumi #devsumiF サンプル:LampLighter ● まず非常に単純なシステムを考える ● 世界にはフラグがひとつだけ存在する ○ 変数 lamp で表す ● プロセスがひとつだけ稼働している ○ 断続的にフラグを反転させる ○ 式で書けば lamp = ~lamp

Slide 58

Slide 58 text

#devsumi #devsumiF lamp: true lamp: false lamp’ = ~ lamp lamp’ = ~ lamp

Slide 59

Slide 59 text

#devsumi #devsumiF VARIABLE lamp (* 初期状態 *) Init == lamp = TRUE (* 状態遷移時の関係 *) Next == lamp' = ~lamp

Slide 60

Slide 60 text

#devsumi #devsumiF #devsumi #devsumiF サンプル:TwinLighter ● フラグがふたつ存在する ○ 変数名は lamp1 と lamp2 ● プロセスがふたつ非同期で稼働している ○ それぞれ P1 と P2 とする ○ P1 は lamp1 を、P2 は lamp2 を反転させる ○ 同時には動かないが、順番はランダムで交互とも限らない

Slide 61

Slide 61 text

#devsumi #devsumiF lamp1: false lamp2: true lamp1: false lamp2: false lamp1: true lamp2: true lamp1: true lamp2: false

Slide 62

Slide 62 text

#devsumi #devsumiF VARIABLE lamp (* 初期状態 *) Init == lamp1 = TRUE /\ lamp2 = TRUE (* 状態遷移時の関係 *) Next == lamp1' = ~lamp1 \/ lamp2' = ~lamp2

Slide 63

Slide 63 text

#devsumi #devsumiF #devsumi #devsumiF PlusCal による生成 ● 生の TLA+ を書くのは人間には辛い ○ そもそも直接、遷移を書けるなら最初から曖昧性などない ● PlusCal と呼ばれる DSL からコード生成 ○ Pascal 風の記法と C 言語風の記法がある ● AWS の事例論文でも有効性を強調 ○ 現場のプログラマからの心理的障壁を下げる効果

Slide 64

Slide 64 text

#devsumi #devsumiF --algorithm LampLighter process P \in { 1, 2 } variable lamp = TRUE; begin while TRUE do lamp := ~lamp; end while; end process; end algorithm;

Slide 65

Slide 65 text

#devsumi #devsumiF --algorithm LampLighter process P \in { 1, 2 } variable lamp = TRUE; begin while TRUE do lamp := ~lamp; end while; end process; end algorithm; ループっぽい記法

Slide 66

Slide 66 text

#devsumi #devsumiF --algorithm LampLighter process P \in { 1, 2 } variable lamp = TRUE; begin while TRUE do lamp := ~lamp; end while; end process; end algorithm; 複数プロセスのインスタンス化

Slide 67

Slide 67 text

#devsumi #devsumiF #devsumi #devsumiF 第 2 章のまとめ ● 形式手法によるシステムの表現 ○ システムを数学的な対象にマッピング ○ 厳密な記述を強制し「イメージの外」の余地を残さない ● 今回は TLA+ をモデル検査器として使用 ○ 研究用だけでなく、国内を含めて産業界で実績がある ○ PlusCal を使用してプログラムっぽく書ける

Slide 68

Slide 68 text

#devsumi #devsumiF #devsumi #devsumiF 3. モデリングと仕様の明確化 Formal Modeling of the Specifications 参考文献:http://muratbuffalo.blogspot.com/2018/12/2-phase-commit-and-beyond.html

Slide 69

Slide 69 text

#devsumi #devsumiF #devsumi #devsumiF TCC パターンの「曖昧」な部分 ● 未定義動作のないシステムの正確な挙動 ○ 各コンポーネントの動作と、非同期に動いた系全体の挙動 ● 保証したい仕様の意味 ○ 不整合とは何か、どういう状況なら許容できるのか ● アルゴリズム外の環境との相互作用 ○ 動作している各サーバの信頼性、ネットワークの状態

Slide 70

Slide 70 text

#devsumi #devsumiF コンポーネントごとに記述 合成は TLA+ に任せる

Slide 71

Slide 71 text

#devsumi #devsumiF ポイント管理 ギフト券管理 銀行口座管理 決済サービス Payment Methods

Slide 72

Slide 72 text

#devsumi #devsumiF fair process Payment begin (* 決済サービス側の挙動 *) end process; fair process Method \in METHOD begin (* 決済手段側の挙動 *) end process;

Slide 73

Slide 73 text

#devsumi #devsumiF #devsumi #devsumiF 決済サービス側の挙動 ● まず Try リクエストを出す ○ モデリングは Try した状態からスタート ● 確定なら Confirm リクエストを出す ○ 全員が OK のレスポンスを返した場合 ● 取り消しなら Cancel リクエストを出す ○ 一人でも OK のレスポンスを返さなかった場合

Slide 74

Slide 74 text

#devsumi #devsumiF try cancel confirm

Slide 75

Slide 75 text

#devsumi #devsumiF try cancel confirm 全員 reserved

Slide 76

Slide 76 text

#devsumi #devsumiF try cancel confirm 一人でも canceled

Slide 77

Slide 77 text

#devsumi #devsumiF variable paymentState = "try" fair process Payment begin either (* Confirm リクエストを発行 *) await confirmable; paymentState = "confirm"; or (* Cancel リクエストを発行 *) await cancerable; paymentState = "cancel": end either; end process;

Slide 78

Slide 78 text

#devsumi #devsumiF variable paymentState = "try" fair process Payment begin either (* Confirm リクエストを発行 *) await confirmable; paymentState = "confirm"; or (* Cancel リクエストを発行 *) await cancerable; paymentState = "cancel": end either; end process; either ... or … で条件分岐

Slide 79

Slide 79 text

#devsumi #devsumiF define (* 全員が準備 OK なら確定できる *) confirmable == \A m \in METHOD: methodState[m] \in { "reserved" } (* 一人でもキャンセルなら全員キャンセル *) cancerable == \E m \in METHOD: methodState[m] \in { "canceled" } end define;

Slide 80

Slide 80 text

#devsumi #devsumiF define (* 全員が準備 OK なら確定できる *) confirmable == \A m \in METHOD: methodState[m] \in { "reserved" } (* 一人でもキャンセルなら全員キャンセル *) cancerable == \E m \in METHOD: methodState[m] \in { "canceled" } end define; forall: 任意の ... exists: 少なくとも一つ存在

Slide 81

Slide 81 text

#devsumi #devsumiF #devsumi #devsumiF 決済手段側の挙動 ● Try に対して仮登録を行う ○ 待機中に Try リクエストを受けたら仮登録状態になる ● Confirm に対して確定処理を行う ○ 自分が仮登録状態ならそれを確定状態に変える ● Cancel に対してキャンセル処理を行う ○ さらに自分自身が失敗した場合もキャンセル状態になる

Slide 82

Slide 82 text

#devsumi #devsumiF idling confirmed reserved canceled

Slide 83

Slide 83 text

#devsumi #devsumiF idling confirmed reserved canceled try 受信

Slide 84

Slide 84 text

#devsumi #devsumiF idling confirmed reserved canceled confirm 受信

Slide 85

Slide 85 text

#devsumi #devsumiF idling confirmed reserved canceled cancel 受信

Slide 86

Slide 86 text

#devsumi #devsumiF idling confirmed reserved canceled cancel 受信 または自分が失敗

Slide 87

Slide 87 text

#devsumi #devsumiF fair process Method \in METHOD begin while methodState[self] \in { "idling", "reserved" } do either (* 待機 → 仮登録 *) or (* 仮登録 → 確定 *) or (* キャンセル *) end either; end while; end process; either ... or … で 3 通りに分岐

Slide 88

Slide 88 text

#devsumi #devsumiF either (* 待機 → 仮登録 *) await methodState[self] = "idling"; methodState[self] := "reserved"; or (* 仮登録 → 確定 *) await methodState[self] = "reserved" /\ paymentState = "confirm"; methodState[self] := "confirmed"; or (* キャンセル *) ... end either;

Slide 89

Slide 89 text

#devsumi #devsumiF either (* 待機 → 仮登録 *) await methodState[self] = "idling"; methodState[self] := "reserved"; or (* 仮登録 → 確定 *) await methodState[self] = "reserved" /\ paymentState = "confirm"; methodState[self] := "confirmed"; or (* キャンセル *) ... end either; 仮登録状態になる

Slide 90

Slide 90 text

#devsumi #devsumiF either (* 待機 → 仮登録 *) await methodState[self] = "idling"; methodState[self] := "reserved"; or (* 仮登録 → 確定 *) await methodState[self] = "reserved" /\ paymentState = "confirm"; methodState[self] := "confirmed"; or (* キャンセル *) ... end either; 確定状態になる

Slide 91

Slide 91 text

#devsumi #devsumiF either (* 待機 → 仮登録 *) ... or (* 仮登録 → 確定 *) ... or (* キャンセル *) await methodState[self] = "idling" \/ (methodState[self] = "reserved" /\ paymentState = "cancel"); methodState[self] := "canceled"; end either;

Slide 92

Slide 92 text

#devsumi #devsumiF either (* 待機 → 仮登録 *) ... or (* 仮登録 → 確定 *) ... or (* キャンセル *) await methodState[self] = "idling" \/ (methodState[self] = "reserved" /\ paymentState = "cancel"); methodState[self] := "canceled"; end either; キャンセル状態になる

Slide 93

Slide 93 text

#devsumi #devsumiF #devsumi #devsumiF TCC パターンの「曖昧」な部分 ● 未定義動作のないシステムの正確な挙動 ○ 各コンポーネントの動作と、非同期に動いた系全体の挙動 ● 保証したい仕様の意味 ○ 不整合とは何か、どういう状況なら許容できるのか ● アルゴリズム外の環境との相互作用 ○ 動作している各サーバの信頼性、ネットワークの状態

Slide 94

Slide 94 text

#devsumi #devsumiF #devsumi #devsumiF 検証したい TCC の性質 ● トランザクションとしての一貫性 ○ Confirmed と Canceded が混在しないか? ○ 混在するとデータに不整合が発生する ● 一連の手続きが完了する保証 ○ いつかは Confirmed もしくは Canceled になる? ○ デッドロックや無限ループに陥ると困る

Slide 95

Slide 95 text

#devsumi #devsumiF #devsumi #devsumiF 安全性と活性 ● 安全性 (Safety) ○ 何か悪いことが「起こらない」ことを要求 ○ 通常のプログラムでのアサーションに近い ● 活性 (Liveness)一連の手続きが完了する保証 ○ 何か良いことが「起こる」ことを要求 ○ 何もしないシステムは無意味なので活性は必須

Slide 96

Slide 96 text

#devsumi #devsumiF A A 「A が成り立つか?」: 「いずれ A が成り立つか? 」: A

Slide 97

Slide 97 text

#devsumi #devsumiF A A 「A が成り立つか?」: 状態に対する条件 「いずれ A が成り立つか? 」: A true false true false

Slide 98

Slide 98 text

#devsumi #devsumiF A A 「A が成り立つか?」: 状態に対する条件 「いずれ A が成り立つか? 」: 状態列に対する条件 A true false true false true false

Slide 99

Slide 99 text

#devsumi #devsumiF 仕様を表現する「言葉」の必要性

Slide 100

Slide 100 text

#devsumi #devsumiF #devsumi #devsumiF 時相論理 (Temporal Logic) ● 通常の論理式に記号を追加した体系 ○ [] A:現時点以降、常に A が成り立つ ○ <> A:現時点以降、いつかは A が成り立つ ● 状態の列に対して真偽を判定 ○ 時間的に幅がある振る舞いについて性質を記述できる ○ 式の真偽の与え方は何種類か存在する (LTL、CTL など)

Slide 101

Slide 101 text

#devsumi #devsumiF <> A : 現時点以降、いずれは A が成り立つ A true false [] A : 現時点以降、常に A が成り立つ A A A A A false true

Slide 102

Slide 102 text

#devsumi #devsumiF (* 確定とキャンセルが混在しない *) Consistency == \A m1, m2 \in METHOD: ~ (methodState[m1] = "confirmed" /\ methodState[m1] = "canceled") (* どの決済手段もいつかは確定もしくはキャンセルになる *) Completed == <>(\A m \in METHOD: methodState[m] \in { "confirmed", "canceled" })

Slide 103

Slide 103 text

#devsumi #devsumiF (* 確定とキャンセルが混在しない *) Consistency == \A m1, m2 \in METHOD: ~ (methodState[m1] = "confirmed" /\ methodState[m1] = "canceled") (* どの決済手段もいつかは確定もしくはキャンセルになる *) Completed == <>(\A m \in METHOD: methodState[m] \in { "confirmed", "canceled" }) 「いつかは」= 時相論理

Slide 104

Slide 104 text

#devsumi #devsumiF いざ検査!

Slide 105

Slide 105 text

#devsumi #devsumiF No errors!

Slide 106

Slide 106 text

#devsumi #devsumiF #devsumi #devsumiF 検証したい TCC の性質(再掲) ● トランザクションとしての一貫性 ○ Confirmed と Canceded が混在しないか? ○ 混在するとデータに不整合が発生する ● 一連の手続きが完了する保証 ○ いつかは Confirmed もしくは Canceled になる? ○ デッドロックや無限ループに陥ると困る

Slide 107

Slide 107 text

#devsumi #devsumiF #devsumi #devsumiF 第 3 章のまとめ ● TLA+ による TCC のモデリング ○ 各遷移が起こりうる条件を分割整理し、漏れをなくす ○ 各コンポーネントごとに記述すれば合成してくれる ● 時相論理による検証 ○ 安全性と活性の両サイドを検証 ○ テストでは難しい「一連の振る舞い」が検査可能

Slide 108

Slide 108 text

#devsumi #devsumiF #devsumi #devsumiF 4. 複雑な実行パスの検証 Check Complicated Behaviour

Slide 109

Slide 109 text

#devsumi #devsumiF #devsumi #devsumiF TCC パターンの「曖昧」な部分 ● 未定義動作のないシステムの正確な挙動 ○ 各コンポーネントの動作と、非同期に動いた系全体の挙動 ● 保証したい仕様の意味 ○ 不整合とは何か、どういう状況なら許容できるのか ● アルゴリズム外の環境との相互作用 ○ 動作している各サーバの信頼性、ネットワークの状態

Slide 110

Slide 110 text

#devsumi #devsumiF #devsumi #devsumiF 決済サービスの故障 ● 先ほどのモデリングは故障しない前提 ○ 直感的なイメージが難しいのはむしろ異常系 ○ 故障の発生はランダムなので分岐が爆発的に増える ● Confirm または Cancel リクエスト後に故障 ○ 故障後はいかなるリクエストも発しない ○ 故障後はずっと故障していて、自動で復旧はしない

Slide 111

Slide 111 text

#devsumi #devsumiF 性質の良いシステム 性質の悪いシステム

Slide 112

Slide 112 text

#devsumi #devsumiF 故障しない 性質の良いシステム 性質の悪いシステム

Slide 113

Slide 113 text

#devsumi #devsumiF 故障しない 性質の良いシステム Crash-Stop 故障 : 故障後、完全に沈黙 性質の悪いシステム

Slide 114

Slide 114 text

#devsumi #devsumiF 故障しない 性質の良いシステム Crash-Stop 故障 : 故障後、完全に沈黙 Crash-Recovery 故障 : 故障後、復活の可能性 性質の悪いシステム

Slide 115

Slide 115 text

#devsumi #devsumiF 故障しない 性質の良いシステム Crash-Stop 故障 : 故障後、完全に沈黙 Crash-Recovery 故障 : 故障後、復活の可能性 ビザンチン故障:サーバが任意の応答を返す 性質の悪いシステム

Slide 116

Slide 116 text

#devsumi #devsumiF つまり決済サーバの故障モデルとして Crash-Stop 性を仮定

Slide 117

Slide 117 text

#devsumi #devsumiF try cancel confirm

Slide 118

Slide 118 text

#devsumi #devsumiF try cancel confirm crash

Slide 119

Slide 119 text

#devsumi #devsumiF Errors!

Slide 120

Slide 120 text

#devsumi #devsumiF #devsumi #devsumiF エラートレースの内容 1. 決済手段サーバ 1, 2, 3 の順に Try が到達し 3 台とも Reserved 状態に 2. 決済サーバが Confirm リクエスト動作中に故障 3. Confirm リクエストは決済手段サーバに到達せず 4. 決済手段サーバは Reserved のまま動けない

Slide 121

Slide 121 text

#devsumi #devsumiF #devsumi #devsumiF フェイルオーバによる冗長化 ● 決済サービスの代替サーバを用意 ○ 代替サーバは故障しないと仮定する ● 代替サーバの挙動 ○ 本体が故障していないかを監視 ○ 本体が正常なら何もしない ○ 故障していたら代わりに Confirm / Cancel リクエスト

Slide 122

Slide 122 text

#devsumi #devsumiF ポイント管理 ギフト券管理 銀行口座管理 決済サービス 代替サービス

Slide 123

Slide 123 text

#devsumi #devsumiF ポイント管理 Reserved ギフト券管理 Reserved 銀行口座管理 Reserved 決済サービス Crash 代替サービス

Slide 124

Slide 124 text

#devsumi #devsumiF ポイント管理 Reserved ギフト券管理 Reserved 銀行口座管理 Reserved 決済サービス Confirm 代替サービス

Slide 125

Slide 125 text

#devsumi #devsumiF ポイント管理 Confirmed ギフト券管理 Confirmed 銀行口座管理 Confirmed 決済サービス Confirm 代替サービス

Slide 126

Slide 126 text

#devsumi #devsumiF crach cancel confirm

Slide 127

Slide 127 text

#devsumi #devsumiF crach cancel confirm 全員 reserved

Slide 128

Slide 128 text

#devsumi #devsumiF crach cancel confirm 一人でも canceled

Slide 129

Slide 129 text

#devsumi #devsumiF Errors!

Slide 130

Slide 130 text

#devsumi #devsumiF #devsumi #devsumiF エラートレースの内容 1. 決済手段サーバが 3 台とも Reserved になる 2. 決済サーバが手段サーバ 1 にのみ Confirm を送った状態で故障 3. 「全員 Reserved」ではないため代替サーバ動作せず

Slide 131

Slide 131 text

#devsumi #devsumiF crach cancel confirm 全員 reserved か、 もしくは最低一人が confirmed

Slide 132

Slide 132 text

#devsumi #devsumiF No errors!

Slide 133

Slide 133 text

#devsumi #devsumiF #devsumi #devsumiF 第 4 章のまとめ ● システムが取りうる異常系をあらかじめ記述 ○ どのような故障を想定するか ○ どのような故障であれば耐えられるように設計するか ● TLA+ による探索 ○ 全探索により仕様に合わない挙動を検出 ○ 人間ではすぐには思いつかないような条件の漏れを指摘

Slide 134

Slide 134 text

#devsumi #devsumiF #devsumi #devsumiF 5. 本日のまとめ Recup the Session

Slide 135

Slide 135 text

#devsumi #devsumiF #devsumi #devsumiF 本日のまとめ ● 自然言語による仕様は曖昧性を持つ ○ 理解しているつもりで意外な見落としの原因になる ● 形式手法によるモデリング ○ 数学的な表現を用いることで厳密な表現が可能に ● より複雑な状況における解析の自動化 ○ 長く複雑な実行パスであっても自動で網羅される