RoomClip 開発者ブログ

AWS DMSでMySQL(RDS)とRedshiftをリアルタイム同期させてみた

こんにちは、Tunnelでエンジニアをしている谷(naotee)です。

RedShiftはwindow関数が使えますし、大量のレコードがあったとしても、集計や分析系のクエリが早く返ってきて便利ですよね。 また、RedShiftに突っ込んだログ系のデータのidの詳細を持っているのがMySQLなんですが、JOINさせる際にできる限り新しいデータで見れる方が良いですよね。 ということで、今回AWS DMSのOngoind Replicationを利用し、MySQL(RDS)とRedshiftをリアルタイム同期させてみました。

DMSとは

「AWS Database Migration Service は、広く普及しているほとんどの商用データベースとオープンソースデータベース間のデータ移行にご利用いただけます。」

AWS Database Migration Service(データベースを簡単かつ安全に AWS へ移行) | AWS

DMSを利用するにあたって必要なもの

  • 同期元DB(source endpoint)
  • 同期先DB(target endpoint)
  • DMS用ec2インスタンス

上記3つは全て同じリージョンである必要があります。 弊社のMySQL(RDS)は東京リージョンに、RedShiftはコスト対策のためバージニアにありましたので、 MySQL(RDS)のクロスリージョンレプリカを利用してバージニアに同期元DBを設置し、バージニアでDMSを設定しました。

同期(タスク)の種類は3つあります。

  • migrate existing data(初期転送のみ)
  • migrate existing data and replicate ongoing changes(初期転送後、差分転送開始)
  • replicate data changes only(差分転送のみ)

今回はRedShiftに0から同期するので「migrate existing data and replicate ongoing changes(初期転送後、差分転送開始)」をタスクで指定します。

DMSの画面での作業の流れ

「Get started」に従うと下記のような流れになります。「cancel」をクリックして、個別に設定することもできます。

  • sourceとtargetにアクセス可能なレプリケーションインスタンスを立ち上げます
  • endpointのsourceとtargetを指定します
  • taskを指定します

MySQL(RDS)で注意が必要な設定

MySQL(RDS)で差分転送を利用するためにはbinログの設定が必要となります。下記を参照ください。

MySQL 互換データベースの AWS Database Migration Service のソースとしての使用

エラー事例

「Check 'stl_load_errors' system table for details. [122502] ODBC general error. (ar_odbc_stmt.c:4063)」というエラーが出たため、stl_load_errorsテーブルを確認すると「Invalid timestamp format or value [YYYY-MM-DD HH24:MI:SS]」というメッセージを確認しました。 MySQLにある0000-00-00 00:00:00というレコードを適切なものに修正すればエラーがなくなりました。

運用中のエラー検知について

タスクがエラーとなって止まった時の検知方法ですが、 AWSのサポートセンターに確認しましたところ、直接アラートを上げる方法ないみたいです。

大きく2つのやり方を紹介してもらいました。

1.AWS CLI にてレプリケーションタスクの状態を取得する方法

例:「aws dms describe-replication-tasks --filter Name=replication-task-id,Values=[レプリケーションタスクID]」

ただし、値を検知してアラートを上げる仕組みを構築する必要があります

2.DMSで出力しているCloudWatchのログから、フィルタパターンに例えば「"]E:"」を指定するようなカスタムメトリックスを作成し、アラームを利用して検知する方法

やってみて

運用中2回停止したことがあり、本番環境から直接参照するデータベースに同期先データベースを利用することは要検証かと思いますが、日々の数値確認や、バッチ処理によるデータ作成のときに利用するには十分活用できると感じました。

参照サイト


この記事を書いた人:naotee

エンジニアのnaoteeです。 サーバーまわりやwebまわりを触っています。データーまわり触るの好きです。


[iOS]特定のイベントを他のViewControllerに(安全に、楽に)伝える

オハツのカキコです☆★☆( ´ ▽ ` )ノTunnelでiOSアプリの制作を担当している富樫です。

さて、本題に移ります。RoomClipでは、投稿されている写真に対して「いいね!」したり、「フォルダに保存」したりすることができます。
それらの機能をスムーズに楽しんでもらうためには、いくつか実現しなければならないユーザ体験があるのですが、その中でもとても基本的でとても渋いものとして、「ある画面で一つの写真に対して『いいね』『保存』などを行った時に、他のスタックしている画面に戻った時にその画面でも該当写真の状態変化が反映されているようにする」というものがあります。以下はイメージ図です。


iOSではこれを実現するために、NSNotificationCenterと、UIViewControllerのpostNotificationを使って別ViewControllerにイベントの通知を行ったりもしたのですが、

  • それぞれのアクションを行った後にpostNotificationする時、いちいち通知の仕様(パラメータの正確な変数名など)に気を配る必要がある
  • 通知を受け取る各画面で、通知のパラメータの仕様(パラメータの変数名や型)に気を配る必要がある

ということがしんどかったので、開発メンバーに相談を行いつつ「安全に、楽に」他画面に通知を出来る仕組みを自前で作りました


通知をするために新たに作ったclass達

醜い図(mini quiz)で恐縮ですが、以下のような構成で4つのclassを準備しました。

NotificationManagerはシングルトンのクラスになっていて、アプリの中で一つだけ存在するようになっています。
NotificationManagerの中でEventは、実際は複数種類のものが存在しており、それぞれTが異なっています。
Tは通知のために必要なパラメータの型が当てられていて、EventsオブジェクトはNotificaionの中で下記のように定義されています。

上記の例の「AddLikeParam」は、いいねをした時に他の画面に伝える必要な情報(いいねした写真のIDなど)を包括しています。


実際の実装


通知を受け取る必要がある画面では、NotificationManagerのなかの然るべきイベントにsubscribeする。

subscribeの引数として、通知を受け取った際の挙動を記述したblockを充てます。
ちなみに、これらの処理は全てUIViewControllerの中に記述するものとしています。


①を行ったUIViewControllerではsubscriptionをフィールドに保持しておき、UIViewControllerが破棄される際には、必ずsubscriptionをunsubscribeする。

Subscriptionはunsubscribeを呼び出すことにより、自身を破棄します。これを、UIViewControllerのdeallocなどで呼び出します。そうしなければUIViewControllerがリークしてしまうことがあります。


通知をPostする必要がある箇所で、然るべきパラメータを準備し、postを行う

これにより、①で記述したアクションが実行されます。
ちなみにviewControllerもPOSTしているのは、ある画面が送った通知を、その画面がそのまま受信するケースがあります。
そして、他画面からの通知と自分の画面からの通知とを区別してハンドリングする必要があるケースもあるからです(①のコードでvc === wselfと記述しているのがそのケースです)。


Eventsでジェネリクスを用いて安全に、迷わないように。。

さて、つらつらと書いてまいりましたが、これまで書いた中で大事だったのはEventsでジェネリクスを用いたことだと思っています。
前述の通り、Eventsの「T」はアクションに対応した通知に必要なパラメータです。
NotificationManagerの中で各アクションに対応するEventsオブジェクトを定義する際に「T」の型もきっちりと定義しておくことで、

  • それぞれのアクションを行った後に通知をpostする時、いちいち通知の仕様(パラメータの正確な変数名など)に気を配る必要がある
  • 通知を受け取る各画面で、通知のパラメータの仕様(パラメータの変数名や型)に気を配る必要がある

といった、前述したヒヤヒヤ感がなくなりました。


以上になります。長文失礼致しました。うーぬ、blogって大変ですね、また次回書く時も頑張ります。。。。


この記事を書いた人:buscemi

TunnelのiOSエンジニアです。 Steve Buscemiに似てます。