こんにちは、pubgで全然ドン勝できない、開発部の大久保です。
今回は弊社が調査含め半年ほどかけて実施した、Aurora移行のお話しをしようかと思います。
ただ、Auroraへ移行するための情報自体は世の中に溢れていると思うので、今回は移行する際に失敗したことや想定外だったことをご紹介しようと思います。
具体的な失敗や想定外をお伝えすることで、移行を考えている方のお役に立てれば幸いです。
移行の概要
とはいえ、さすがに大まかにでもどのように移行をしたかをご紹介しないと、失敗も共有できないので、簡単に共有します。
今回弊社が行った移行は、EC2上にホストしているMySQLをAuroraに移行する、というものです。RDSからAuroraに移行する、というものではありません。
では、ものすごく簡素化した移行の図で、移行の全体像をお伝えします。
移行前
なにも行っていない状態はこんな感じでした。
バックアップ用のEC2インスタンスはバックアップや開発用のデータの元となるdumpデータを取るサーバです。当時はOregonリージョンに立てていました。これは別リージョンにもリアルタイムのバックアップをとっておく目的で存在しています。
このサーバ、今回の想定外の1つなので、敢えてご説明しています。
移行準備
移行予定のAuroraインスタンスを立て、そこをSlaveとしてレプリケーションをすることでデータを移行します。
移行後
移行当日に、AuroraをMasterに昇格させ、アプリケーション側のDBの向き先を一気にAuroraに変更しました。 その他、バックアップ用のサーバが、クロスリージョンリードレプリカになっています(バックアップはAuroraのSnapShotだけでなく、sqlのdumpデータも欲しいので…)。
実際はもう少し複雑な構成なのですが、シンプルにするとこのような流れです。
移行手順としてはオーソドックスだと思います。
失敗・想定外だったこと
では、上記手順でAurora移行をした際に発生した問題をご紹介します。大きくは3つでした。
Aurora→EC2上のMySQLへのレプリケーションはSSLにできない
上記図でいうバックアップサーバは、別リージョンのEC2インスタンス上にMySQLを立て、リアルタイムのバックアップを別リージョンに取るために使っていたのですが、料金を考えると、Aurora移行後も信頼性の低いEC2インスタンス上のMySQLでも十分でした。ですので、当初の予定では移行後も安いEC2インスタンスを使う予定でした。
しかし、調査しているとAurora→外側のMySQLサーバという向きではレプリケーションがSSL通信できないことがわかりました。
別リージョンとなるとさすがにSSL通信をしたかったため、高額ですがクロスリージョンリードレプリカを使うことになってしまいました。今はこのサーバが別リージョンのリアルタイムバックアップと、定期的なdumpデータバックアップを取得する役割を担っています。
これはそもそも別リージョンにリアルタイムバックアップを取る必要があるのか…という話なのですが…。
レプリケーション間のTimezoneがズレていたことによるデータズレ
移行前のMySQLサーバと、移行予定のAuroraサーバのTimezoneがズレていることにより、移行当日のデータ差分チェックで実際に差分が発生してしまい、移行作業をロールバックしています。
具体的には、移行前のMySQLはSYSTEM、というタイムゾーン設定で、これはOSのタイムゾーンを用います。移行前のOSのタイムゾーンはJSTでした。
一方、AuroraのOSのタイムゾーンはUTCですので、そのままSYSTEM設定でレプリケーションをすると、UTCとしてレプリケーション時のクエリが流れてしまいます。
この現象により、データのズレが発生しました。
移行前のMySQLサーバのタイムゾーンを変更することで問題は解決しました。
フェイルオーバー時に旧コネクションを維持してしまう問題
Auroraは障害時、迅速にフェイルオーバーしてくれるのですが、フェイルオーバーをテストしていると、コネクション周りで1つ問題が発生しました。 Auroraのフェイルオーバーは、Master側に障害が発生すると、SlaveのリードレプリカがMasterとして昇格するのですが、障害が発生したMaster側が、復旧後Slaveとして戻ってきます。 つまり、MasterとSlaveが逆転します。 この動きと、Webアプリケーションで行うコネクションプーリングとの相性があまり良くないのです。 具体的には、Webアプリケーションが持つMaster用のコネクションがフェイルオーバー時に破棄されずに保持されており、そのコネクションがSlaveとして復旧したAuroraインスタンスに接続しようとしてしまい、更新時にエラーが起きる、というものです。 毎回コネクションを作成すれば回避できる問題ですが、できればコネクションは使いまわしたいので、以下の解決を取りました。
Tomcatの場合
参考にした記事は以下の通り。
こちらは、context.xmlで設定するValidationクエリで、コネクションの状態がReadOnlyかどうかをチェックするストアドを作成し、それを使う、というものです。 Tomcatはこちらの方法で対応しました。
Railsの場合
Railsでは、基本的にconnectionは永続的に使うようになっているのですが、それを定期的に破棄する設定を加えました。 参考にした記事は以下の通り。
activerecord-refresh_connection
を使うと、コネクションが一定数利用されると破棄されるようになります。
この対応はフェイルオーバーした直後にコネクションの向き先が変わることはないのですが、一定回数使われれば新しく接続されるため、一定時間が経過すれば正しいconnectionが得らるようになります。
クロスリージョンリードレプリカを作成するためのbinlogを有効にすると性能が落ちる
具体的には、binlog_format
をMIXED
にしているのですが、これにより性能が劣化することがわかりました。ただし、弊社ではクロスリージョンリードレプリカの作成は必須だったので、受容しました。
詳細な指標は、以下のqiita記事に記載されていますが、かなり劣化しています。
その他、あまり語られることが少ないが、やらないといけなかったもの
- エラーログ・スロークエリログ
定期的にS3にログを吐き出す対応を、Lambdaで行っています。
まとめ
以上、弊社が遭遇したAurora移行時の失敗・想定外の出来事です。Aurora移行前は、簡単に移行できるでしょ…と思っていましたが、細かい問題が色々ありました。大抵のことはそうですよね…。
尚、移行して数ヶ月経過しましたが、特に問題は発生していません(気づいていないだけ?)。
これから移行を検討されている方、是非参考にしてみてください!
シンクロ・フードではエンジニアを募集しています。こんなインフラサイドの記事を書いていてアレなのですが、最近ではRailsをバリバリ書ける方を募集中です…。是非ご応募ください!