Apolloとデータ移行の課題
Apolloはシートリップ(Ctrip)が開発したオープンソースの設定管理センターで、分散デプロイをサポートしており、非常に便利で人気があります。一般的にはアプリケーションサービスの設定として使用されることが多いですが、一部の企業ではビジネスデータを保存しているケースもあります。Apolloの設計上、データベース内のCommitテーブルとReleaseテーブルが非常に大きくなる可能性があります。ここでの「大きさ」とは、テーブルの列サイズが大きいことを指し、移行時に困難が伴います。
データ保存の仕組み
Commitテーブルについて
Apolloの仕組みを理解している方なら、Commitテーブルが項目に対するCUD(作成、更新、削除)操作のたびにレコードを追加することをご存知でしょう。各操作ではChangeSetsという変更データセットが追加されます。Properties形式のビジネスデータの場合、変更があるたびにApolloはデータ全体が変更されたと見なし、ChangeSetsフィールド全体を挿入します。
Releaseテーブルの課題
より厄介なのはReleaseテーブルです。ApolloはNameSpaceを単位として公開を行うため、この点ではNacosに劣ります。そのため、公開のたびにReleaseレコード、ReleaseHistory、ReleaseMessageが追加されます。ReleaseのConfigurationsフィールドには、公開のたびにNameSpace全体のPropertiesが含まれ、辞書形式で保存されます。これらのPropertiesにビジネスデータが保存されている場合、Configurationsフィールドのサイズが想像以上に大きくなることは明らかです。
データベース移行の課題
最も移行が困難なのはCommitテーブルとReleaseテーブルです。不適切な使用によりフィールドデータ量が過大になり、クエリパフォーマンスに深刻な影響を及ぼし、移行効率を著しく低下させます。クエリが遅いのであれば、各NameSpaceの最後のリリースのみを移行すれば十分ではないでしょうか。
解決策
私たちが移行を行った際、運用チームは全テーブルの移行を試みましたが、毎回タイムアウトしてしまいました。さらに、Apolloは私が手動で構築したものであり、その仕組みについては比較的詳しかったため、より適切なアプローチを検討しました。
CommitテーブルとReleaseテーブルには、各NameSpaceの最新のスナップショットのみを保持すれば十分です。他の履歴データは必要ありません。データ量が最も大きいNameSpaceは、コミット回数も高く、移行時に最も問題となります。
移行用SQL例
Commitテーブルから有用なデータを抽出する方法:
SELECT
*
FROM
(
SELECT
record_id,
ROW_NUMBER() OVER (
PARTITION BY application_id,
cluster_name,
namespace_name
ORDER BY
record_id DESC
) AS row_num
FROM
`ConfigCommit`
) AS filtered_data
WHERE
row_num = 1
LIMIT
100
必要に応じてLIMIT値を調整し、主キーであるrecord_idで指定データをクエリーし、DataXなどのツールを使用して移行すれば、非常に迅速に完了します。
テーブルの最適化
row_num > 1のデータを削除してテーブルを最適化できますが、データ量が大きくフラグメント化の問題もあるため、有効データを一時テーブルにコピーしてから名前変更する方法が安全です。
CREATE TABLE `ConfigCommit_temp` LIKE `ConfigCommit`;
INSERT INTO `ConfigCommit_temp` SELECT * from `ConfigCommit` c
WHERE record_id in (
SELECT
record_id
FROM
(
SELECT
record_id,
ROW_NUMBER() OVER (
PARTITION BY application_id,
cluster_name,
namespace_name
ORDER BY
record_id DESC
) AS row_num
FROM
`ConfigCommit`
) AS filtered_data
WHERE
row_num = 1
);
RENAME TABLE `ConfigCommit` TO `ConfigCommit_backup`, `ConfigCommit_temp` TO `ConfigCommit`;
DROP TABLE `ConfigCommit_backup`;
ANALYZE TABLE `ConfigCommit`;
外部キーであるapplication_idについては、定時タスクを設定して履歴データを定期的にクリーンアップし、テーブルサイズを管理することが可能です。