Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ステートフルなアプリケーション のダウンタイムを 10 秒以下 にすることを目指して

ステートフルなアプリケーション のダウンタイムを 10 秒以下 にすることを目指して

第6回Reactive System Meetup in 西新宿
https://reactive-shinjuku.connpass.com/event/202517/

Kazuki Negoro

March 05, 2021
Tweet

More Decks by Kazuki Negoro

Other Decks in Programming

Transcript

  1. 私 は何者︖ 根来 和輝 Negoro Kazuki TIS 株式会社 テクノロジー&エンジニアリングセンター ミッション

    ⾼可 用システムを安価 なインフラで 課外活 動 Akka 実践 バイブル執筆 Scala Matsuri 登壇 @negokaz negokaz © 2021 TIS Inc. 2 / 39
  2. Lerna Stack ⾼可 用性 と⾼ スループットを実現 するソフトウェアスタック ⾃⼰修復可能 なアーキテクチャにより高可 用性

    を実現 Event Sourcing を用いたロックフリーな永 続化 方式により 高スループットを実現 © 2021 TIS Inc. 3 / 39
  3. 稼働率 99.9999% を実現 できるか︖ キャッシュレス決済などミッションクリティカルな業務 で 要求 される可 用性 許

    容できる年間停 止時間は 31.5 秒 従来 、専 用のハードウェアを搭載 した高価なサーバー を用意 して実現 してきた稼働 率 © 2021 TIS Inc. 4 / 39
  4. 稼働率 99.9999% を実現 できるか︖ キャッシュレス決済などミッションクリティカルな業務 で 要求 される可 用性 許

    容できる年間停 止時間は 31.5 秒 従来 、専 用のハードウェアを搭載 した高価なサーバー を用意 して実現 してきた稼働 率 当 時の Lerna では難 しいことが明 らかに © 2021 TIS Inc. 5 / 39
  5. Lerna Stack が直⾯ した稼働率 の限界 レイヤー 障害 種別 ダウンタイム ネットワーク

    ネットワーク分断 ~20s Keepalived ノード停 止 ~ 5s HAProxy ノード停 止 ~ 5s アプリ(Akka) ノード停 止 ~15s Cassandra ノード停 止 0s MariaDB(Galera) ノード停 止 ~ 2s © 2021 TIS Inc. 6 / 39
  6. Lerna Stack が直⾯ した稼働率 の限界 レイヤー 障害 種別 ダウンタイム ネットワーク

    ネットワーク分断 ~20s Keepalived ノード停 止 ~ 5s HAProxy ノード停 止 ~ 5s アプリ(Akka) ノード停 止 ~15s Cassandra ノード停 止 0s MariaDB(Galera) ノード停 止 ~ 2s © 2021 TIS Inc. 稼働 率 99.999% (年間 5.26 分以 下の停 止)が限界 7 / 39
  7. アプリの MTTR を10 秒以下 にしたい ただし、ターゲットとする業務領域 では 強整 合性 が求

    められる 結 果整 合性 で問題なければ Akka の Replicated Event Sourcing という選択肢 がある © 2021 TIS Inc. MTTR: mean time to recovery(平均復旧 時間) Replicated Event Sourcing • Akka Documentation 8 / 39
  8. ダウンタイムの原因 は何なのか︖ 強整 合性 を保障 しながらスケーラブルな Event Sourcing を 実現

    するために Lerna Stack では Akka Persistence Akka Cluster Sharding を組 み合わせて使う © 2021 TIS Inc. 9 / 39
  9. ダウンタイムの原因 は何なのか︖ 強整 合性 を保障 しながらスケーラブルな Event Sourcing を 実現

    するために Lerna Stack では Akka Persistence Akka Cluster Sharding を組 み合わせて使う この組 み合わせでネットワーク分断障害 の フェイルオーバーを考える © 2021 TIS Inc. 10 / 39
  10. ネットワーク分断障害 の解 決方法 Split Brain Resolver を使う それぞれの側 が到 達できないノードを確認し、

    停⽌ する と判 定したほうが自らをシャットダウンする © 2021 TIS Inc. これは keep-majority の例 (多 数派を維 持する) 11 / 39
  11. さらに伸 びる合意形成 のための時間 合意形成 のための時間はノード数に合わせて ⻑ くとることが推奨 されている cluster size

    stable-after + down-removal- margin 5 14s 10 20s 50 26s 100 40s © 2021 TIS Inc. Split Brain Resolver • Akka Documentation 14 / 39
  12. Split Brain Resolver がなぜ必要 か 強整 合性 (一貫性 )を維持 するため

    ネットワーク分断 時に無条件 で Entity を回復 させると、 同 じ Entity が複 数のノードに存在 する状態 になり 一貫性 が損 なわれる可 能性 がある © 2021 TIS Inc. 15 / 39
  13. ネットワーク分断 とノード停⽌ ネットワーク分断 とノード停⽌ は区別 できない ノード同⼠ は定期的 に相互 にヘルスチェックを行って

    応 答があればノードが生きているとみなす 応 答がないときは ノードが停 止しているのでしょうか? ネットワークが断線 しているのでしょうか? © 2021 TIS Inc. 18 / 39
  14. ネットワーク分断 とノード停⽌ ネットワーク分断 とノード停⽌ は区別 できない ノード同⼠ は定期的 に相互 にヘルスチェックを行って

    応 答があればノードが生きているとみなす 応 答がないときは ノードが停 止しているのでしょうか? ネットワークが断線 しているのでしょうか? ノード停 止であってもフェイルオーバーに ネットワーク分断 と同 じ時間がかかる © 2021 TIS Inc. 19 / 39
  15. ダウンタイムを減 らすには 一貫性 の保証 を Split Brain Resolver に頼らない Entity

    を複 製しておきリカバリ時の IO を不 要に © 2021 TIS Inc. 20 / 39
  16. どうやってそれを実現 するのか︖ 一貫性 の保証 を Split Brain Resolver に頼らない Raft

    が複数 ノードに複製 された Entity の一貫性 を保証 © 2021 TIS Inc. 23 / 39
  17. どうやってそれを実現 するのか︖ 一貫性 の保証 を Split Brain Resolver に頼らない Raft

    が複数 ノードに複製 された Entity の一貫性 を保証 Entity を複 製しておきリカバリ時の IO を不 要に © 2021 TIS Inc. 24 / 39
  18. どうやってそれを実現 するのか︖ 一貫性 の保証 を Split Brain Resolver に頼らない Raft

    が複数 ノードに複製 された Entity の一貫性 を保証 Entity を複 製しておきリカバリ時の IO を不 要に 常に複製 が存在 しているためリカバリ時の IO は不要 © 2021 TIS Inc. 25 / 39
  19. どうやってそれを実現 するのか︖ 一貫性 の保証 を Split Brain Resolver に頼らない Raft

    が複数 ノードに複製 された Entity の一貫性 を保証 Entity を複 製しておきリカバリ時の IO を不 要に 常に複製 が存在 しているためリカバリ時の IO は不要 Raft によりフェイルオーバー時の 障害 検知より後の時間を全て削 減できる © 2021 TIS Inc. 26 / 39
  20. 私 たちが目指 したもの ダウンタイムが 10 秒以下 強整 合性 が保障 される

    スケーラビリティがある 学習 コストが低 い(Akka ユーザーにとって) © 2021 TIS Inc. 28 / 39
  21. アーキテクチャ © 2021 TIS Inc. Cluster Sharding と似 た Actor

    の階層 スケールアウト時は Shard が移 動 Entity のイベント列 を Shard が Raft で同期 30 / 39
  22. ダウンタイムを計測 してみた 目標のダウンタイム10 秒以下 を達成 できたのか? 達成 !!! 🎉 レイヤー

    障害 種別 ダウンタイム ネットワーク ネットワーク分断 8.0s アプリ(Akka) ノード停 止 6.0s © 2021 TIS Inc. 32 / 39
  23. API Akka の既存 ユーザーが実装 しやすいよう Akka Classic Persistence と似 た

    API を提 供 class CountActor extends ReplicationActor[Int] { private[this] var count: Int = 0 ... // 複製の中で代表者だけが実行する override def receiveCommand: Receive = { case CountUp(_, amount) => replicate(Incremented(amount)) { event => count = count + event.amount } // 代表者以外の複製が実行する // ただし、代表者においても起動直後は状態を復元するために呼ばれる override def receiveReplica: Receive = { case Incremented(amount) => count = count + amount ... } } © 2021 TIS Inc. 34 / 39
  24. API Raft のログコンパクションのため Actor の状態 は スナップショットとして自動的 に永 続化 される

    class CountActor extends ReplicationActor[Int] { private[this] var count: Int = 0 // 現在の"状態"を返す override def currentState: Int = count override def receiveCommand: Receive = { case CountUp(_, amount) => replicate(Incremented(amount)) { event => count = count + event.amount } override def receiveReplica: Receive = { case Incremented(amount) => count = count + amount // Actor の復元時、最後に保存した "currentState" を最初に適用 case SnapshotOffer(snapshot: Int) => count = snapshot } } © 2021 TIS Inc. 35 / 39
  25. Akka 公 式プロダクトとの⽐較 一貫性 リカバリタイム リソース消費 Replicated Event Sourcing 結

    果整 合性 0s - Akka Cluster Sharding 強整 合性 19s 以 上 ※1 - Akka Entity Replication 強整 合性 10s 以下 大 © 2021 TIS Inc. ※1: Akka 公 式の推奨値 で構成 した場合 36 / 39