DB安定化への挑戦:RDS Proxy導入レポート
背景
tacomsでは、camelというサービスを展開しています。
このサービスは、1つの端末で複数のデリバリーサービスを管理できるようにするサービスであり、管理の効率化を行うことが可能となります。
tacomsのシステムは、店舗様向けのサービスであり、多数の店舗が使用するため、24時間365日稼働する必要があります。そのため、長時間のメンテナンスウィンドウを確保することが困難であり、システム停止を最小限に抑えながらDB操作を行う必要がありました。
RDS Proxyとは
RDS ProxyはAWSのフルマネージドデータベースプロキシサービスです。アプリケーションとRDSの間でコネクションプーリングを行い、データベース接続を効率的に管理します。これによりアプリケーションの可用性向上、データベースのフェイルオーバー時間短縮、セキュリティ強化を実現します。
RDS Proxyに期待した効果
期待した効果は以下2つになります。
1. フェイルオーバー時間の短縮
従来の構成では、RDSインスタンスのフェイルオーバー時に新しい接続の確立が必要でしたが、RDS Proxyを使用することで接続情報がプロキシ側でキャッシュされ、再接続が迅速に行われます。公式ドキュメントによると、フェイルオーバー時間が最大65%短縮されるとされています。
2. コネクション管理の効率化
RDS Proxyは接続プールを管理し、データベースへの接続をプロキシすることで、データベースエンジンへの負荷を軽減します。アプリケーションからの多数の接続要求を少数のデータベース接続にマッピングすることで、リソースの効率的な利用が可能になります。
RDS Proxy導入時に確認事項
レイテンシの悪化
データベースには、Amazon RDS プロキシの使用ではなく直接接続をいつする必要がありますか?の箇所で、RDS Proxyを導入することで平均5ミリ秒レイテンシが追加されることが公式ドキュメントで記載されています。
弊社のサービスでは、これくらいのレイテンシは許容できると判断しました。
ピン留め
ピン留めとは、特定のセッションがデータベース接続に「固定」される状態を指します。ここでいう固定とは、コネクションを特定のクライアントが占有してしまうことを指します。このピン留めが多発すると、RDS Proxyのコネクションプーリングの効果が低下し、結果としてデータベース接続の効率的な再利用ができなくなります。
各メトリクスの関係性
RDS Proxyのメトリクスは結構あるので、その関係性を理解しておく必要がありました。
クラスメソッドさんの記事が非常にわかりやすかったです。
https://dev.classmethod.jp/articles/rds-proxy-metrics-that-relate-connections/ より引用
アプリケーションから RDS Proxy への接続
RDS Proxyのドキュメントで、ドキュメントには以下2つの考慮事項が記載されています。
クライアント接続の最大有効期間: RDS Proxy では、クライアント接続の最大有効期間は 24 時間です。この値は設定できません。クライアント接続が予期せず切断されないように、プールは最大接続時間を 24 時間未満に設定してください。
文字通り、RDS Proxyに接続できる最大時間です。
24時間を超えると勝手に切られるので、アプリケーションで意図して切ってくださいねということで理解しています。
クライアント接続アイドルタイムアウト: RDS Proxy は、クライアント接続の最大アイドル時間を適用します。予期せぬ接続の切断を避けるため、RDS Proxy のクライアント接続アイドルタイムアウト設定よりも低い値のアイドル接続タイムアウトをプールに設定します。
このアイドルという定義が「RDS Proxyを使ってない」ことと理解しています。
使ってない時間があった場合、無駄だから接続切ろうねと理解してます。
Goでの考慮事項
弊社ではサーバーの実装にGoを使用しています。実装は以下のようになります。
SetConnMaxLifetime
を24時間以内に設定しつつ、SetConnMaxIdleTime
で設定されている時間を超えれば使用してないと判断し、接続を切るという実装になります。
db, err = sqlx.Connect("mysql", dbConfig)
...
...
// クライアント接続の最大有効期間を示す
db.SetConnMaxLifetime(time.Hour * 12)
// クライアント接続アイドルタイムアウトを示す
db.SetConnMaxIdleTime(time.Minute * 5)
図で示すと、全体像は以下のようなイメージです。
詳細は、この記事が非常にわかりやすいので、ぜひご一読してみてください。
https://please-sleep.cou929.nu/go-sql-db-connection-pool.html より引用
結果
メリット1: フェイルオーバー時間が短縮される
RDS Proxyを導入することで、DBのフェイルオーバー後の復旧時間を大幅に改善することができます。
tacomsのシステムは24時間稼働することが必須であるため、フェイルオーバー時に影響範囲を小さくすることができます。
デメリット1: レイテンシが悪化する
Datadog APMの結果を確認すると、100msから1sレイテンシが悪化していることを確認しました。
これくらいのレイテンシであれば、tacomsのシステムは許容できると判断しました。
デメリット2: ピン留めが発生する
期待する結果はこのピン留め(DatabaseConnectionsCurrentlySessionPinned)がなくなることでしたが、メトリクスが上昇していることを確認しました。調査していると、どうやらprepared statementを使用していることが原因ということがわかりました。AWSのドキュメントにもピン留めが発生する条件として記載されています。RDS Proxyのログを見るとprepared statementが原因で、ピン留めされていることを確認することができます。
2025-04-10T08:04:40.038Z [WARN] [proxyEndpoint=camel-backend-cluster-proxy-read-endpoint] [clientConnection=1584104317] The client session was pinned to the database connection [dbConnection=2759305824] for the remainder of the session. The proxy can't reuse this connection until the session ends. Reason: A protocol-level prepared statement was detected.
アプリケーションの実装では、明示的にprepared statementを使用していなかったので、なぜだろうとなってました。結果、sqlパッケージ内部でprepared statementを使用しているのが原因のようでした。
ピン留めは発生しますが、コネクションが増加する度にピン留めが発生するわけではないし、コネクションもまだまだ余裕があったので、ピン留め自体の事象は仕方ないとし、許容することにしました。
まとめ
RDS Proxyの導入により、DBフェイルオーバー時間の短縮を実現できました。これは24時間365日稼働が必須のtacomsシステムにとって重要な成果だと思っています。
一方で、レイテンシの悪化(100ms-1s程度)やGoのSQL実装によるピン留め発生というデメリットも確認できましたが、現状のシステム要件では許容範囲内と判断できました。特にピン留めについては、コネクション数に余裕があり実質的な問題は発生していません。
そのため、RDS Proxyの導入はtacomsのシステムの可用性向上に効果的な選択だったと評価しています。
Discussion