こんにちは、KIYONOエンジニアです。
本日は、「Amazon Aurora 高可用性設定の罠」ということで実際に著者がハマってしまった内容を備忘としてまとめます。
Amazon Aurora 高可用性設定(リードレプリカの作成)によってデータが更新されていない!!の現象に陥ったらもしかすると同じパターンかもしれないのでご参考ください。
そもそもAmazon Aurora 高可用性設定とは?
今回の高可用性の意味としては、ここではリードレプリカの作成を意味します。
リードレプリカの設定によって、読み取り処理に関する負荷分散および自動フェイルオーバーが可能になります。
読み取り処理の負荷分散に関しては、書き込みと読み取りのインスタンスを分けることで、処理が2方向にいくことから負荷が分散するというのはなんとなくイメージできるのではないでしょうか。
フェイルオーバーについては、プライマリーインスタンスに何かしらの障害がある際に、リードレプリカがプライマリーに自動で昇格します。
詳細は以下をご参考くださいませ。これ以上の説明については本日のメイントピックではないため割愛します。
実際にAmazon Auroraでした設定と発生した不具合
設定
Amazon Aurora
- リードレプリカの作成
- リードレプリカのオートスケーリング設定
- カスタムエンドポイントの設定
設定の目的は負荷分散と障害時のリカバリーの観点から設定しました。
アプリケーション側
- Auroraのカスタムエンドポイントへのリクエストを出し分け実装
実装内容としてはFetch関連のSQL実行の場合は、リードレプリカへのエンドポイントを使い、それが以外のSQL実行の際は、プライマリーのエンドポイントを使うように出し分けました。
不具合
確かに負荷分散はできるようになったのですが、CMSの特定の機能で更新したはずの内容が反映されないという事象が発生しました(汗
原因
不具合の主な要因としては、プライマリーインスタンスに書き込んでからリードレプリカに値が反映されるまでにラグがあるという部分を考慮できていなかったためです。
具体的には、リードレプリカに反映されるまで100ミリ秒未満の時間がかかります。
引用元:https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.Replication.html
更新されなかったアプリケーションの処理について
全ての更新がうまく行かないかというとそうではなくて、ある特定の機能だけうまく更新できないというのが検証でわかりました。具体的には以下のような処理の場合に発生しました。
- 特定の情報を更新する(プライマリーインスタンスを使う)
- 書き込んだ情報を読み込む(リードレプリカを使う)
- 読み込んだ情報に補足して、再度更新する(プライマリーインスタンスを使う)
100ミリ秒の考慮をしない場合に、以下の状態になり値が更新されない状態になっておりました。
- 特定の情報を更新する(プライマリーインスタンスを使う)・・・値が更新される
- 書き込んだ情報を読み込む(リードレプリカを使う)・・・リードレプリカにプライマリーの情報が反映されていない
- 読み込んだ情報に補足して、再度更新する(プライマリーインスタンスを使う)・・・反映されていない情報で再度値を更新する
対策
対策としては上記を取りました。(もっといい方法あったかもしれませんが…)
- 特定の情報を更新する(プライマリーインスタンスを使う)
- 更新直後にリードレプリカに情報が反映されるまで、Sleepを実行
- 書き込んだ情報を読み込む(リードレプリカを使う)
- 読み込んだ情報に補足して、再度更新する(プライマリーインスタンスを使う)
最後に
いかがだったでしょうか。今回の過去トラが誰かの参考になればと思います。
コメント