クイック エンジニアリングブログ

株式会社クイック Web事業企画開発本部のエンジニアリングチームが運営する技術ブログです。

AWS RDS Auroraの復元機能を利用した「データマート」実装の話し

こんにちは。クイックSREチームのみっちーです。

最近はデータドリブンの流れが加速してますね。弊社でもそういった方向を目指し日々社内整備を進めているわけですが、最近社内でこんな声があがりました。

「在宅でも、もっと気軽に分析業務ができる環境があればいいのにな」

なるほど。じゃあ作ってみよう!ということで、今日はそのときの話しをご紹介したいと思います。

目次

1. はじめに

2. なぜいまデータマートなのか

3. やったこと~設計編~

4. やったこと~構築編~

1. はじめに

データマートとは

企業などで情報システムに記録・蓄積されたデータから、 利用部門や用途、目的などに応じて必要なものだけを抽出、集計し、 利用しやすい形に格納したデータベースのこと。

「マート」(mart)は「小売店」の意。

data.wingarc.com

データマートとデータウェアハウス(DWH)の違い

データマートは企業の総データ(DWH)の中から、目的に応じて一部を取り出したデータベースです。 DWHは特定のシステムに使われるものではなく、全社で活用するためのインフラです

it-trend.jp

2. なぜいまデータマートなのか

データマートのメリットとは

利用部門ごとに使用するデータや分析内容が異なることが多いため、その利用部門が必要とするデータのみをデータウェアハウスから抽出したり、その利用部門が必要とする分析データをあらかじめ集計することにより、分析レスポンスを向上できる。

データマート - Wikipedia

弊社が抱えていた課題

本来であればDWHを構築して、それを起点に分析を進めていく流れが望ましいのでは?そんな声が聞こえてきそうです。
確かにその通りなのですが、当時の弊社では以下のような課題がありました。

  • 現状、データ分析ニーズ(利用部門)が限られており、DWHのように広い範囲のものではなく「特定のデータのみ」があればよい。
  • 在宅/社外からも、個人情報にアクセスせず「安全に分析」業務を行いたい。
  • あらかじめ加工されているデータベースを使い、「分析時間を短縮」したい。
  • そもそもDWHが出来上がるまで、待てない。

上記の課題を解決しつつセキュリティリスクも排除するような仕組みを迅速に用意する目的もあり、今回の「データマート」の導入に踏み切りました。

2. やったこと~設計編~

設計時のマストチェックポイント

  • セキュリティ、負荷の両面から「プロダクション環境とは分離する」こと。
  • 抽出業務において不要なデータ(特に個人情報)は一切含んでいないこと。
  • 抽出したいデータは、リアルタイム性が必要なのかを見極めること。例えば、数時間前のデータでもOKなのか。
  • 運用コストも極力抑えること。22時~29時(PM10時~翌AM5時)までは稼働しなくて良い。

具体的な設計内容

  1. データマート専用の接続先ドメインを1つ用意。
  2. AWS RDS Aurora「特定の時点への DB クラスターの復元」機能を利用して「別筐体として復元」する。 docs.aws.amazon.com
  3. そこに不必要なデータを除外するSQLを流す。
  4. データマートの接続先(DNS)を、復元されたDBのエンドポイントに向ける。
  5. 毎晩23時付近で、データマート用のRDSを削除。
  6. 上記2~5をJenkinsのスケジューラーで毎日実行。

3. やったこと~構築編~

データマートの接続先ドメインを用意。

  • AWS Route53上に、任意のアクセスポイントを用意します。
  • ここでは、dm.919.test という名前と仮定します。

AWS RDS Aurora「特定の時点への DB クラスターの復元」機能を利用して復元する。

  • restore-to-timeは ”YYYY-MM-DDTHH:MM:SSZ”の形式で指定(GMT+9H)します。
  • 例えば、2020年10月18日15時の時点に復元したい場合は、「2020-10-18T15:00:00Z」の様に指定します。
    • 環境依存かもしれませんが、復元可能時間は「最大でも24H前程度?」のようです。
    • テスト時に数日前を指定したらできませんでした。

~主要な箇所のみ抜粋~

# 復元時間の指定
RESTORE_TIME=”YYYY-MM-DDTHH:MM:SSZ"

# 復元先のクラスターを作成する
$ aws rds restore-db-cluster-to-point-in-time \
    --source-db-cluster-identifier "clone-from-cluster-name"\
    --db-cluster-identifier "create-new-cluster-name"\
    --restore-type full-copy \
    --restore-to-time ”$RESTORE_TIME”\
    --vpc-security-group-ids  "sg-0123456789" \
    --db-subnet-group-name "rds-test-subnet01"\
    --db-cluster-parameter-group-name  "rds-test-paramgroup01"

# 復元先のDBインスタンスを作成する
$ aws rds create-db-instance \
    --db-cluster-identifier "create-new-cluster-name"\
    --engine "aurora-mysql"\
    --engine-version "5.7.mysql_aurora.2.07.2"\
    --promotion-tier "0" \
    --db-instance-identifier "create-db-instance01" \
    --availability-zone "ap-northeast-1a" \
    --db-instance-class "db.t3.small"\
    --db-subnet-group-name "rds-test-subnet01"\
    --db-parameter-group-name "rds-test-paramgroup01"

そこに不必要なデータを除外するSQLを流す。

  • 必要なSQL文を用意してmysqlコマンドを使って流し込みます。

データマートの接続先(DNS)を、復元されたDBのエンドポイントに向ける。

  • Route53でDNS管理をしているので、以下のスクリプトを組みました。
#!/bin/bash

set -x

# 操作対象レコードのゾーンID
SET_RECODE_ZONEID=<操作対象レコードのゾーンID>

# 更新先のDBクラスター名
RECODE_VALUE=<更新先のDBクラスター名>

# 上記の存在確認
# なければジョブ終了
aws rds describe-db-clusters --db-cluster-identifier <DBインスタンス名>
if [ $? -ne 0 ];then
    echo "Error: $RECODE_VALUE is not found."
    exit 1
fi

# 更新用のレコードjsonの作成
echo -e "{\"Comment\":\"<わかりやすいコメント入れてね>\",\"Changes\":[{\"Action\":\""UPSERT"\",\"ResourceRecordSet\":{\"Name\":\"dm.919.test \",\"Type\":\"CNAME\",\"TTL\":<TTL値>,\"ResourceRecords\":[{\"Value\":\" "${RECODE_VALUE}"\"}]}}]}" | jq '.' > $WORKSPACE/update_recode.json

# 更新前のバックアップ処理
aws route53 list-resource-record-sets --hosted-zone-id $SET_RECODE_ZONEID > $WORKSPACE/before_recode.json

# 更新処理
aws route53 change-resource-record-sets --hosted-zone-id $SET_RECODE_ZONEID --change-batch file://$WORKSPACE/update_recode.json

# 更新前後での比較
aws route53 list-resource-record-sets --hosted-zone-id $SET_RECODE_ZONEID > $WORKSPACE/after_recode.json
diff $WORKSPACE/before_recode.json $WORKSPACE/after_recode.json
if [ $? -ne 1 ];then
    echo "Error: DNSレコードの更新ができていない可能性があります。確認してください。"
    exit 1
else
    echo "DNSレコードの更新完了"
fi

毎晩24時付近で、データマート用のRDSを削除。

  • 以下のシェルをJenkinsのスケジューラーを設定して動かします。
#!/bin/bash

# 削除対象のクラスター名を指定
DELETE_TARGET="<削除対象のDBクラスター名>"

# クラスター内に居る削除対象のインスタンスを洗い出す
INSTANCES=`aws rds describe-db-clusters --db-cluster-identifier $DELETE_TARGET | jq -r '.DBClusters[0].DBClusterMembers[].DBInstanceIdentifier'`

# インスタンスの削除
for INSTANCE in $INSTANCES; do
  aws rds delete-db-instance --db-instance-identifier $INSTANCE --skip-final-snapshot --delete-automated-backups
done

# クラスターの削除
aws rds delete-db-cluster --db-cluster-identifier $DELETE_TARGET --skip-final-snapshot

以上で終了です。

最後に。
本来はDWHのような「統合的なデータ整備」を進めていくことが、これからは必要になってくると思います。
ただ今回の様にデータマート環境を作る方がコスパが良い場合もありそうです。
将来の技術的負債にならぬよう慎重に、かつ状況に応じて柔軟に事業貢献を狙っていきたいですね。



\\『明日のはたらくを創る』仲間を募集中です!! // 919.jp