1K Views
August 20, 25
スライド概要
2025年8月21日に開催された「データベースの負債解消への道のりLunch Talk」で使用した資料です。
ウェルスナビ株式会社 技術広報チームの公式アカウントです。
技術的負債を乗り越え、Readレプリカ振り分けで得た データベースパフォーマンス向上
⾃⼰紹介 尾形 涼介 (Ogata Ryosuke) ウェルスナビ株式会社 ロボアド開発グループ サービス機能開発チーム ウェルスナビでは ● 2024年ウェルスナビ株式会社に新卒として⼊社 ● サービスサイト‧APIの開発に従事 ひとこと ● 名前も⾎液型もO型です 2 @2025 WealthNavi Inc.
アジェンダ 1. ウェルスナビのシステム概要 2. 課題:DBパフォーマンス悪化 3. 技術的な負債:振り分けできないクエリの存在 4. レプリカラグによる設計⾒直し 5. 振り分けたはずが...Open Session in Viewの罠 6. 結果とまとめ 3 @2025 WealthNavi Inc.
1. ウェルスナビのシステム概要 2. 課題:DBパフォーマンス悪化 3. 技術的な負債:振り分けできないクエリの存在 4. レプリカラグによる設計⾒直し 5. 振り分けたはずが...Open Session in Viewの罠 6. 結果とまとめ 4 @2025 WealthNavi Inc.
資産運用ロボアドバイザー 「 WealthNavi 」 5 ※ ⼀般社団法⼈⽇本投資顧問業協会「契約資産状況(最新版)(2025年3⽉末現在) 『ラップ業務』『投資⼀任業』」を基にネット専業業者を⽐較 ウエルスアドバイザー 社調べ(2025年6⽉時点) ※ 画⾯はイメージです。
システム概要図(パフォーマンス改善前) 提携先向け 全自動 システム バッチ Aurora MySQL ※画像はイメージです Webアプリ アプリのAPI Writerのみ 社内業務 システム Spring Bootで開発 6 @2025 WealthNavi Inc.
1. ウェルスナビのシステム概要 2. 課題:DBパフォーマンス悪化 3. 技術的な負債:振り分けできないクエリの存在 4. レプリカラグによる設計⾒直し 5. 振り分けたはずが...Open Session in Viewの罠 6. 結果とまとめ 7 @2025 WealthNavi Inc.
パフォーマンス悪化の発端 重いバッチ処理が動いている時間と、ユーザーのアクセスが集中している時間が重なり、 インスタンスサイズ(db.r6i.16xlarge)の閾値(64 アクティブセッション: ⾚点線)を超える⽇がある。 →放置すればパフォーマンス低下やDBのクラッシュの恐れがある 8 @2025 WealthNavi Inc.
WriterとReaderにクエリを振り分けて、負荷分散 インフラチームと協議し、WebアプリAPIの⼀部のエンドポイントとバッチのクエリ をWriterインスタンスとReaderインスタンスに振り分ける⽅針へ Writer (マスター ) Webアプリ API (一部のエンドポイント ) バッチ 取得系のトランザクションのみ Readerへ接続 9 Reader (レプリカ ) Reader2 Reader3 Readerはスケーラブル 9 @2025 WealthNavi Inc.
1. ウェルスナビのシステム概要 2. 課題:DBパフォーマンス悪化 3. 技術的な負債:振り分けできないクエリの存在 4. レプリカラグによる設計⾒直し 5. 振り分けたはずが...Open Session in Viewの罠 6. 結果とまとめ 10 @2025 WealthNavi Inc.
参照しかしていないトランザクションで謎の更新 振り分けをすると、参照しかしていないエンドポイントで、readonlyエラー The MySQL server is running with the --read-only option so it cannot execute this statement 2019年代から起きている歴史的技術的負債にブチ当たる 11 @2025 WealthNavi Inc.
再現させると過去にタイムスリップ 更新した⽇時を管理をしているLoginDateというカラムに対して 更新処理が⾛り(コードを書いてないのに)、必ず18分59秒巻き戻る。 LoginDateカラム Before: 1754-01-01 09:00:00 After: 1754-01-01 08:41:01 12 @2025 WealthNavi Inc.
タイムスリップの原因 原因は、LoginDateカラムを1754年(江⼾時代)に設定していたこと 年代 タイムゾーン 1888年以降 ⽇本標準時JST(UTC+9時間) それ以前 地⽅時LMT (UTC+9時間18分59秒) DBでは1754年のデータをJSTとして認識 (1754-01-01 09:00:00) Hibernate側はLMTとして扱うため、+18分59秒 (1754-01-01 09:18:59) HibernateはDBと18分59秒差分があると認識し DBの⽅を-18分59秒に更新してしまう (1754-01-01 08:41:01) 13 @2025 WealthNavi Inc.
hibernateのバージョンを上げて解決 hibernate-java8 を5.0.12.Final にアップデート ZonedDateTime.ofInstant が優先される LMTのオフセットを考慮して変換してくれるため、巻き戻りをしない 14 @2025 WealthNavi Inc.
1754年に設定していた背景 この LoginDate が1754年になっていたのは、データ移⾏時に、⽇付で絞り込みをする際に 全件取得するために意図的に古い⽇付を設定していた ● このような暫定対応は、移⾏時には便利でも、⻑期的には技術的負債になることが ある ● 時代をまたぐ⽇付の扱いは、タイムゾーンやライブラリの仕様により予期せぬ挙動 を引き起こす 15 @2025 WealthNavi Inc.
1. ウェルスナビのシステム概要 2. 課題:DBパフォーマンス悪化 3. 技術的な負債:振り分けできないクエリの存在 4. レプリカラグによる設計⾒直し 5. 振り分けたはずが...Open Session in Viewの罠 6. 結果とまとめ 16 @2025 WealthNavi Inc.
レプリカラグにより設計⾒直し:2回同じお知らせが出る お知らせを読んだ際に、再度同じお知らせが出てしまう また同じお知らせが出る 読む 17 @2025 WealthNavi Inc.
ALB→パスベースでの振り分け-クラスター分割前 ECSの書き込みと読み取りのサービス単位で、writerをreaderを分割 ロードバランサーでパスベースの振り分けを行い、レプリカに振り分けをしていた しかしこの構成だとレプリカラグが発生してしまう api-cf api-lb api aurora-writer api-reader aurora-reader 18 @2025 WealthNavi Inc.
レプリカラグとは [公式ドキュメントから引⽤] プライマリインスタンスからアップデートをレプリケートする際の遅延時間 ● Auroraクラスタは、同じストレージを共有している ⼀⽅で、バッファープールはインスタンスごとに独⽴して管理される ● そのためWriterとReaderで、同じデータがバッファープールに格納されていた場合、Readerのバッ ファープールが更新されないと新しいデータは参照できない ● つまり、直前の更新が反映されない状態で読み取りが⾏われるため、ユーザーに古いデータを返してし まうリスクがある https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraMonitoring.Metrics.html 19 @2025 WealthNavi Inc.
ALB→コードベースでの振り分け-クラスター分割後 レプリカラグの懸念から、 ECSのサービス単位で分割は行わず 同一サービス内でWriter/Readerを構成 →レプリカラグが発生しないメソッドだけレプリカに向ける api-cf api-lb api aurora-writer aurora-reader 20 @2025 WealthNavi Inc.
ALB→コードベースでの振り分け レプリカへの振り分けは Spring Bootの @Transactional(readOnly = true) を活用し、コードベースで実現。 整合性を保ちつつ読み取り負荷を分散できる構成を実現 21 @2025 WealthNavi Inc.
1. ウェルスナビのシステム概要 2. 課題:DBパフォーマンス悪化 3. 技術的な負債:振り分けできないクエリの存在 4. レプリカラグによる設計⾒直し 5. 振り分けたはずが...Open Session in Viewの罠 6. 結果とまとめ 22 @2025 WealthNavi Inc.
リリース直前に、またヤツが出た リリース直前のQAチームの最終確認で、またread onlyエラーが出ていたことが発覚 Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed 読み取り専⽤のトランザクションでfindbyxxx(参照系) 読み取り専⽤のトランザクション外のsave中に read onlyエラー(書き込み系) 23 @2025 WealthNavi Inc.
OSIV(Open Session in View)よるreadOnly属性の“残留” HTTPリクエストのライフサイクル全体にわたってHibernateのセッションを維持する仕組み [Spring Bootではデフォルトで有効] ● Viewの描画が終わるまでセッションを開いておくことで、遅延ロードが成功するようになるのが利 点 ● 本事象では、Hibernateのセッションがリクエストスコープで管理されるため、コネクションの解放 タイミングが遅れる。 ○ saveは、Propagation.REQUIRED というデフォルトの設定により、既存のセッションに参加 ○ 結果引き伸ばされた読み取り専⽤コネクションに、saveで実⾏してしまう ● つまり別トランザクションでも、同じリクエスト内であれば 、読み取り専⽤コネクションで実⾏し てしまう恐れがある 24 @2025 WealthNavi Inc.
OSIVでread onlyエラーが出たイメージ図 HTTPリクエスト全体の動き DB DB Propagation.REQUIREDで、 読み取り専⽤のコネクションを 流⽤してエラー リクエスト 開始 findbyxxx save DBへのコネクション は読み取り専⽤のまま viewに描画 リクエスト 終了 OSIVで、セッションがHTTPリクエスト全体に伸ばされ、読み取り専⽤のコネクションが残留 25 @2025 WealthNavi Inc.
release_mode=after_transaction を有効に spring.jpa.properties.hibernate.connection.release_mode=after_transaction ● この設定により、トランザクション終了時にコネクションを解放する意図する挙動に戻す ● OSIVを無効にしてもいいが、影響範囲が大きすぎるので却下 26 @2025 WealthNavi Inc.
1. ウェルスナビのシステム概要 2. 課題:DBパフォーマンス悪化 3. 技術的な負債:振り分けできないクエリの存在 4. レプリカラグによる設計⾒直し 5. 振り分けたはずが...Open Session in Viewの罠 6. 結果とまとめ 27 @2025 WealthNavi Inc.
結果とまとめ(WebアプリAPI) アクティブセッション数(Writer)は、51→28に減少(45%の改善) writerのみ reader writer 28 @2025 WealthNavi Inc.
レプリカ振り分けの結果(バッチ) Writerインスタンスの平均アクティブセッション(AAS)は約10削減 writer 約60 reader 約20 writer 約40 reader 約30 (前日から10増加) 29 @2025 WealthNavi Inc.
まとめ 現状の成果 writerに向いていた負荷は分散されて、明らかな改善効果を確認できた 次のステップ ● 負荷そのものの低減 ● WebアプリAPIでは、⼀部の読み込みエンドポイントのみの対応なので拡⼤ そこには技術的負債の解消も含まれるため、 簡単ではないが本質的な改善を⽬指していく 30 @2025 WealthNavi Inc.
Zennでも本発表を投稿しています この取り組みは、Zennの記事にも投稿しています。 リリース前に公開した内容ですが、よろしければご覧ください。 DB負荷改善の道のり:技術的負債解消から始まった挑戦 31 @2025 WealthNavi Inc.
We are hiring!! エンジニア採⽤強化中! カジュアル⾯談もお気軽にどうぞ! ウェルスナビ © WealthNavi Inc. All Rights Reserved. 採用 32
【重要な注意事項】 ● 本資料は、断定的判断を提供するものではなく、情報を提供することのみを⽬的としており、いか なる種類の商品も勧誘するものではありません。最終的な決定は、お客様⾃⾝で判断するものと し、当社はこれに⼀切関与せず、また、⼀切の責任を負いません。 ● 本資料には将来の出来事に関する予想が含まれている場合がありますが、それらは予想であり、ま た、本資料の内容の正確性、信頼性、完全性、適時性等を⼀切保証するものではありません。本資 料に基づいて被ったいかなる損害についても、当社は⼀切の責任を負いません。また、当社は、新 しい情報や将来の出来事その他の情報について、更新⼜は訂正する義務を負いません。 ● 本資料を利⽤することによりお客様に⽣じた直接的損害、間接的損害、派⽣的損害その他いかなる 損害についても、当社は⼀切の責任を負いません。 商号等:ウェルスナビ株式会社 金融商品取引業者 関東財務局長(金商) 第2884号 加入協会:日本証券業協会 一般社団法人日本投資顧問業協会 33 @2025 WealthNavi Inc.