Work Records

日々の作業記録です。ソフトウェアエンジニアリング全般から、趣味の話まで。

複数のRDSから1台のEC2にレプリケーションをする方法 複数MySQL編

以前こんな記事を書きましたが、もうちょっといい方法を思いついたので更新。
qiita.com

そもそもマルチソースレプリケーションが辛いところ

MySQLがトラブると全部アプリケーションのレプリが止まる

レプリケーション元が大量にある場合、セットアップだけでも結構な時間を要する。
せっかく設定が終わったのに、その段階でMySQLレイヤーでのトラブルが起ると辛い。MySQLがstopもしくはクラッシュしてデータが壊れた場合、全ての設定をやり直す羽目になる。

一つだけ止めるといったことができない

MySQLのパラメータを更新したい場合がある。オンラインで変更可能なものもあるが、MySQLの再起動を必要とするものもある。
全てのデータベースが一つのMySQLに乗っていると、MySQLのstop/startの作業とパラメータの反映も全てのデータベースに波及する。

全部同じMySQLのバージョンとパラメータで起動する

アプリケーションによってはMySQLのバージョンが違ったり、パラメータを変えたかったりするかもしれない。
そういったことは、マルチソースレプリケーションレプリケーションをうけるのは不可能になる。

レプリケーションのCHANNEL管理

10個くらいチャンネルが増えてくると結構めんどくさいことに。
たまーにレプリケーションが止まった時に、エラーになったクエリだけskipしたかったりするのだけど、channel対応していないコマンド(変数)があるとかなり管理が面倒になる。
SQL_SLAVE_SKIP_COUNTERとか。

Auroraが5.7ベースではない

マルチソースレプリケーションMySQLの5.7からサポートされている機能だが、レプリケーション元としてAWS Auroraを利用している場合バージョンの不一致が起きる。
データを閲覧するだけであれば実際に大きな影響はないのだが、index系の調査でEXPLAINを打って実行計画を確認したり、実際にindexを貼ってみてクエリのパフォーマンス改善具合を確かめる時にオプティマイザの挙動が異なるために望んだ結果が得られない場合がある。

実際に、slaveでは問題なくindexが効くのに、実際のmasterのauroraでは早くならないという場面に出くわした。

ただし、JOINはできなくなる

1MySQL上に複数のデータベースがあることで解決する一つの問題はJOINができるということだと思う。
当然webアプリケーションのようにクエリのパフォーマンスが求められるところでは使うことはないとは思うが、分析などクエリのパフォーマンスを求めないようなところでは便利かもしれない。オススメはしない。

そこで、dockerによる複数MySQLの1台のEC2での起動を試してみた

1台のEC2上に複数のMySQLを起動してそれぞれにレプリケーションを受けさせる

図にしてみる。
f:id:kenjiszk:20171209081711p:plain

docker-composeの利用

EC2上に複数のMySQLを立ち上げるために今回はdocker-composeを利用した。
設定をファイルに落としておけるのと、別EC2でもえいやっと一気にmysqlがたくさん上がってくれるため。
設定ファイルの例を以下に。各MySQLでポートだけずらしておき、my.cnfだけ外部ファイルを読むようにして修正可能にしている。

app1:
  image: mysql:5.6
  volumes:
    - "./my.cnf.utf8mb4:/etc/my.cnf:ro"
  ports:
    - "13306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: root
app2:
  image: mysql:5.6
  volumes:
    - "./my.cnf.utf8mb4:/etc/my.cnf:ro"
  ports:
    - "23306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: root
app3:
  image: mysql:5.6
  volumes:
    - "./my.cnf.utf8mb4:/etc/my.cnf:ro"
  ports:
    - "33306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: root

Auroraからのレプリケーション設定

このページが詳しいので割愛
docs.aws.amazon.com

課題

JOIN問題

MySQLが別ホスト(別docker)になるのでJOINはできなくなる。

負荷問題

MySQLは別れたが、OSは同一のものを使っているのでマシンが落ちたらそれは全滅。

AWS Auroraの機能拡張

こんな機能があればAuroraだけで完結できるので、AWSさんよろしくお願いします。
あらゆるインフラの足回りをフルマーネージドで完結させたい!!

Auroraのクラスタ内で、readのendpointからは参照がこないようなreaderの作成

これができると、クラスタ内の一つのインスタンスを負荷の高いクエリや、分析用のクエリを受ける場所として用意できる。

書き込みが可能なレプリカ

もう一つの要件として、分析用途などでは必要のないデータのマスキングをしたいという要望がある。
現時点ではレプリカに対して書き込みを行うとエラーになるので、特定のフラグが立っているレプリカだけ書き込みも許可できるようなると嬉しい。


しかし、RDSやAuroraを使い始めてからあんまりMySQLのコアな機能の詳細を追わなくなってきた感があるなあ。。