変更データ（CDC）を利用したデータ同期検討

この記事はZOZOテクノロジーズ [#2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech2) 23日目の記事になります。
昨日は、[@amagasu1234](https://qiita.com/amagasu1234) さんによる「[Google reCAPTCHA v3をRuby On Railsに入れてみました〜](https://qiita.com/amagasu1234/items/98fa8960746c944b6e8c)」でした。

また、今年は全部で5つのAdvent Calendarが公開されています。

- [ZOZOテクノロジーズ #1 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech)
- [ZOZOテクノロジーズ #2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech2)
- [ZOZOテクノロジーズ #3 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech3)
- [ZOZOテクノロジーズ #4 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech4)
- [ZOZOテクノロジーズ #5 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech5)

# はじめに
Change Data Capture （以下 CDC という） について調査をしていたので、内容をまとめようと思います。
そもそも、なぜ CDC を検討したのかについても説明します。

ZOZOTOWN で利用している主な DB が SQL Server になります。
社内では様々なサービスが稼働しており、各サービスから SQL Server へ接続があります。

![service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324247/9fd40297-e0c1-32bd-8ecf-b0dd29325b91.png)

ここ数年、用途別に SQL Server 以外の DB を利用するケースが増えてきました。
毎回課題となるのが「移行（データ同期）をどのように行うか」です。
また、1度きりの移行なら良いのですが、各サービスからデータ登録されるのが元となる SQL Server であるため移行先に常時データ同期を求められる場合が多いです。

各サービスをマイクロサービス化し、直接新しい DB へ読み書きできるようにするのが理想ですが、まだ実現には時間が掛かりそうです。

ということで、SQL Server から他DB へのデータ同期に CDC を利用することを考えました。
CDC を利用することで各クラウド特有のDB （例： Aurora、 BigQuery など）へのデータ同期が可能になります。

![replication.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324247/15d49359-ca9e-95f5-5e29-b87de004d888.png)


# CDC について
CDC は、データ変更キャプチャと呼ばれており、DB で発生した変更情報を追跡することが出来る機能になります。
別の記事で概要をまとめています。
[SQL Server の Change Data Capture（CDC）機能確認](https://qiita.com/tsurumiii/items/91f95add623b8c24f8d5)

CDC を使うことで元となる SQL Server の変更情報を追跡することが可能となります。
これだけはデータを同期先に反映させることができないため、データ同期用のツールを使います。

# Debezium
[Debezium](https://debezium.io/) はDBの変更をイベントストリームに変換することができる分散プラットホームです。
SQL Server に CDC を設定し変更を追跡、変更情報を取得し、他のDB へ連携ということが可能になります。

![debezium.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324247/f9dfcd7a-6e1d-604f-eae2-e846338155e6.png)

上記のように、Debezium は、kafka を利用して、他のDB への連携を行うことができます。
SQL Server 及び、Elasticsearchは例であるため、他のDB に変えることができます。

別の記事で概要をまとめています。
[Debezium で MySQL の変更データを取得する](https://qiita.com/tsurumiii/items/3447010e3124d272570c)
[Debezium で SQL Server の変更データを取得する](https://qiita.com/tsurumiii/items/00770a8928f1b40b4d13)

# 問題点
CDC + Debezium により他DB へデータ同期できることが分かりました。
しかし、問題点がいくつかあることが分かりました。

- SQL Server の CDC を利用した場合、初期データ移行を別途考える必要がある。CDC は設定した時点からのデータが追跡されます。そのため、既に入っているデータを追跡することができません。すべてのデータを一度更新するか、別の方法で初期データを移行してからでないとデータを同期できません。
- テーブルの変更（DDL）が自動で反映されない。例えば、カラムの追加や削除があった場合に変更された内容が、CDC の変更情報として保存されますが、それが Debezium で取得できません。何か別で変更を検知して、反映させる仕組みが必要となります。

### 注意点

- CDC を利用すると SQL Server上に変更データが保存されます。つまりデータの更新が多い場合や、保存期間が長い場合、かなりのデータ量となるため気をつける必要があります。
- 変更データの保存（書き込み）があるため、SQL Server に少なからずオーバーヘッドがあります（トリガーよりはオーバーヘッドが少ないと言われています）。

### 備考
別の記事でテーブルの列を変更にした場合に何が起こるのかをまとめています。
[SQL Server の Change Data Capture（CDC）で列の変更があった場合の対処](https://qiita.com/tsurumiii/items/867f82f454c251d125e4)

# CDC + Debezium 検討結果

追加開発（初期移行や DDL対応）や運用を考え、「CDC + Debezium」は使わないことにしました。
もちろん作り込めば出来ないことはないのですが、そこまでやる程ではないと判断しました。
CDC について理解が深まったことは良かったです。

# 今後
データ同期の要望がなくなったわけではないため、現在は [attunity replication](https://www.insight-tec.com/products/Attunity/Replicate) を試しています。
Debezium との違いは、Debezium が無償であるのに対して attunity replication は有償である点です。
また、attunity replication であっても SQL Server の　CDC 設定は必要になります。
結局データの変更情報を取得するには元となる DB で変更情報を出力する必要があるということです。
attunity replication は以下の機能が魅力的でした。

- 初期データ同期が可能
- 同期完了した後でもデータの再同期（全データ入れ替え）が可能
- DDL による変更に対応

他にも多々機能はありますが、Debezium で仕組みを考えないと実現出来なかったことが出来ることが多い印象です。
余談ですが、AWS DMS の裏側は attunity のようです。
こちらはまだ Production で利用はしていないので、今後も検証を続けていきます。
今回の記事はここまでになります！

アドベントカレンダー明日以降も続きますので、ぜひ他の方の記事も見てください！！