ランサーズ(Lancers)エンジニアブログ > AWS > Aurora > RDS Aurora から Redshift のデータ同期事情

RDS Aurora から Redshift のデータ同期事情

tomohiro|2016年10月14日
Aurora

こんにちは、ランサーズのtomohiroです。最近はバス釣りにはまっています。大人になって始める趣味ののめり込み具合は半端ないですね。

ランサーズでは、数ヶ月前にリリースしたQuantにおいて、データ分析を行うために Redshift を使用しています。ただし、Redshiftに入れているデータのソースはサービスで使用している RDS Aurora になるため、Aurora から Redshiftへデータを同期する必要があります。単純な MySQL の export/import と違い、いくつか制約があるので一筋縄では行かない時もありますが、そんな物なんとでもなります。
今回は、色々と Redshift の運用で使っていたツールやはまった罠等を軽く紹介したいと思います。

そもそも私はMySQLでの運用・開発経験が中心で、Redshift(postgresqlも含め)をほぼ触った事なかったので、基本的な所でつまづいたりもしてますが、暖かく見守っていただけると嬉しいです。

Aurora から Redshift への同期

まずはデータの同期からです。これが出来ないと何も始まりません。
グーグル先生に「mysql redshift データ コピー」で調べると、見慣れない “AWS Data Pipe…” の文字。色々他の結果もあさりますが、AWSが用意している物なら、と思いちょっと深掘りする事にしました。

こうして AWS Data Pipeline というサービスに出会ったのですが、簡単に説明しますと、データの変換と移動を自動化するツールです。しかも 「RDS から Aurora へのコピー用テンプレート」という物が用意されているため、設定値を埋めていくだけでだいたいできちゃいました。できちゃいましたとか言ってますが、実際は慣れるまで少し時間がかかりました。

AWS Data Pipeline の中身

data_pipelineAWS Data Pipeline でテンプレートを選ぶとpipeline設定画面に移るのですが、その見た目が上の画像になります。画面左側にはデータフローが自動的に設定されて、画面右側に各データフローブロックの設定入力項目が並ぶので、地道にひとつひとつ記入していきます。自由度が高い分、記入する項目が多いので、わりと面倒です。(テーブル単位なので、複数テーブルを同期する場合は複数Pipeline設定する必要があるみたいです。これ間違ってたらショックです。。。これまでの苦労が)

実は上の AWS Data Pipeline を実行すると、裏では m1.small EC2インスタンスが立ち上がり、よしなに RDS から S3 データをエクスポートし、よしなに変換をかけつつ S3 から Redshift にデータをインポートしていきます。(すいません、細かい挙動まで追ったわけではないので、微妙に実際とは違うかもしれないです)そのため、EC2がRDSとRedshiftにアクセス出来るようにセキュリティーグループを用意・指定する必要があったり、ダンプデータを保存するS3のパスを準備する必要があります。

Data Pipeline は複数のタスクで成り立っているのですが、複数タスクによってデータフローが作られるので、直前のタスクの成功をトリガーに順番にタスクを実行されます。そのため、途中で失敗してもリトライするように設定でき、リトライ上限に行くと、実行を途中でキャンセルします。

Pipelineは単発で手動実行する事も可能ですが、スケジューラーを設定する事も出来てcronのような使い方も可能です。弊社では一日に一回テーブル同期のバッチを実行しています。(冬眠pipelineも放置していると月いくらとお金がかかるみたいなので、気をつけてください)

すぐに次の罠にはまる

無事テーブルを連携出来てから数日、Data Pipeline が ”disk space full” 的なエラーでコケてました。最安のRedshift構成で走らせていたので、 160GBしかディスク容量がないのはわかっていたのですが、さすがに埋まるには早かったので焦りました。

結論、postgresql無知な自分が知らなかったのは、VACUUMとANALYZEが必要だったと言うこと。大量行の挿入・変更・削除を行うと即時にディスク容量が開放されないらしく、crontab で VACUUMとANALYZEを実行するシェルを回すようにしています。

ディスク容量問題でいうと更に続きがあり、同期中のあるテーブルが100GBくらいの大きさになった時、Data Pipeline が同じく、”disk space full” 的なエラーをたまに吐くようになりました。Redshiftのperformanceグラフを見る限り、空き容量は 200GBくらいありそうで、容量がいっぱいになるっておかしくないか?って思っていました。

これもまた私の無知(ドキュメント読めやって話し)だったのですが、Redshift のデータのインポートに使う COPY コマンドはデータソースの約2.5倍ほどの空き容量が必要との事。そりゃ、あっと言う間に同期できなくなりますよね。ちなみに、Redshift の UNLOAD や COPY コマンドはローカルファイル等使用出来ず、すべてのファイル操作は S3 経由になります。それまでの Aurora や MySQL の運用ではサーバーから、うりゃって mysqldump やインポートをやっていたので、新鮮でした。だいぶ S3 まわりの権限設定等の勉強になりました。それはまた別に日に話すとします。。。その日が来る事があれば。

こうなると、このまま全更新をするのはそもそも無謀なので、差分更新する事にしました。Data Pipeline の InsertMode という設定があって、”OVERWRITE EXISTING(プライマリキー、ソートキー、ディストキーを使って、既存行を上書く)”という設定にしていたので、後は取得するデータを絞るだけ。これは、DataNodes の SrcRDSTable > Select Query に WHERE分を追加するだけです。これだけで無事、差分更新出来ました。

もっと早くやっときゃよかった。

最後に

他にも色々 Redshift 使ってやってるんですが、まとまりがなくなってきたのでこの辺にしようと思います。

自分は Data Pipeline なるものを今回初めて知り、本当にこれが最適解だったのかは定かではないのですが、とりあえずは運用は回っています。この他にも、Redshift の運用でいろんなシェルスクリプトや、 rails のタスクも動いていたりしますが、その話しもまた別の機会があれば書きます。

駄文長文、最後まで読んでいただきありがとうございます。