10年続くサービスのデータを1日未満のメンテナンスウィンドウで安全に移管する
by
masawada
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
10年続くサービスのデータを 1日未満のメンテナンスウィンドウで 安全に移管する 2024-10-15 Hatena Engineer Seminar #31 「少年ジャンプ+」 サーバーサイド編 id:masawada / id:momochi29 1
Slide 2
Slide 2 text
2
Slide 3
Slide 3 text
長時間メンテナンスで実施したこと ● 他社システムからGigaViewerへのデータ移行 ● 動作確認 ● GigaViewer for Apps版 少年ジャンプ+の配信 3
Slide 4
Slide 4 text
このセッションのテーマ ● 他社システムからGigaViewerへのデータ移行 ● 動作確認 ● GigaViewer for Apps版 少年ジャンプ+の配信 4
Slide 5
Slide 5 text
このセッションのテーマ ● 素朴に実施すると数週間かかる移行を、どう 1日未満のメンテナンスウィンドウに収めたか ● 巨大なシステムのデータ移行を実施するに あたってのテクニックや心構え 5
Slide 6
Slide 6 text
自己紹介 id:masawada ● データ移行のリード ● 全般的な設計から 渉外までなんでも担当 ● マンガメディア開発の チーム歴は5年程度 ● 「ふつうの軽音部」 が好きすぎる 6
Slide 7
Slide 7 text
二部構成 ● 少年ジャンプ+のデータ移行事情 ○ id:masawada ● 移行の自動検証について ○ id:momochi29 7
Slide 8
Slide 8 text
少年ジャンプ +の データ移行事情 8
Slide 9
Slide 9 text
データ移行は総合格闘技 9
Slide 10
Slide 10 text
データ移行は総合格闘技 ● 旧システムのデータを新システムに横流しする ○ ではない ● モデリングの違いを理解して翻訳する作業 10
Slide 11
Slide 11 text
データ移行は総合格闘技 ● 旧システムのデータを新システムに横流しする ○ ではない ● モデリングの違いを理解して翻訳する作業 ○ だけでもない 11
Slide 12
Slide 12 text
データ移行は総合格闘技 要求の整理 設計 費用見積もり キャパシティプランニン グ 実装 検証 パフォーマンスチューニング スケジュール の検討 リハーサル走行 本番走行 移行後対応 などなど… 30分では話せない! 12
Slide 13
Slide 13 text
今日話すこと ● 少年ジャンプ+のデータ移行に対する要求 ● どのような実装で実現したか ● うまくやるには 13
Slide 14
Slide 14 text
少年ジャンプ +の データ移行に対する要求 14
Slide 15
Slide 15 text
他社システムとGigaViewerの関係 ● 他社システム(旧システム) ○ 旧少年ジャンプ+ アプリ版のバックエンド ○ 2014年9月22日にサービスイン ● GigaViewer(新システム) ○ もともと少年ジャンプ+ Web版を配信 ○ 2017年1月18日にサービスイン 15
Slide 16
Slide 16 text
他社システムとGigaViewerの関係 ● もともと以下データを同期していた ○ 雑誌・話の原稿やメタデータ ○ ユーザアカウント情報 ○ ユーザの定期購読情報 ○ ユーザが購入した雑誌の情報 16
Slide 17
Slide 17 text
他社システムとGigaViewerの関係 ● それぞれのシステムで管理していたデータの例 ○ 話のレンタル履歴 ○ 話をレンタルするためのコイン ○ 閲覧履歴 ○ コメント ○ などなど 17
Slide 18
Slide 18 text
移行するデータの特徴 ● とにかくデータが多い ○ 当初想定では、ほぼ最強のAuroraインスタンスの リソースを使い切って数週間かかる見込み ● メンテナンス直前まで書き込みが発生する ○ 支配的なデータはユーザの閲覧履歴・コインなど ○ マンガを読む機能も課金も止められない 18
Slide 19
Slide 19 text
移行プロジェクトに対する要求 ● メンテナンスウィンドウは1日未満 ○ 日毎に連載があるため ● 移行元の機能ロックは実質不可能 ○ 支配的なデータは止められないため 19
Slide 20
Slide 20 text
どうするか ● ユーザのデータだけをまず移行することに ○ 原稿やメタデータは旧システムに入稿して同期 ○ 別途移行プロジェクトを立ち上げる ● とはいえこれで減らせる量は少ない…… 20
Slide 21
Slide 21 text
どのような実装で 実現したか 21
Slide 22
Slide 22 text
必要なデータを オンラインで少しずつ移行 22
Slide 23
Slide 23 text
分割移行 ● 旧システムのDBスナップショットをいただいて復元 ● 特定の時刻範囲に作成・更新されたデータを移行 ○ を繰り返す 23
Slide 24
Slide 24 text
分割移行 スナップショット 2024/2/1 スナップショット 2024/3/1 2014/1/1 2024/1/1 2014/1/1 2024/1/1 1回目の移行 移行済 2024/2/1 2024/2/1 2回目の移行 2024/3/1 24
Slide 25
Slide 25 text
分割移行 ● Step Functions + AWS Batchを採用 ○ 「魔法のiらんど」のデータ移行でも実績がある ○ 詳しくは: Hatena Engineer Seminar #14* ● Step Functionsで依存関係を管理しつつ実行 * https://speakerdeck.com/tkzwtks/hatena-engineer-seminer-number-14-data-migration 25
Slide 26
Slide 26 text
分割移行 26 { “since”: “2014-01-01T00:00:00+09:00”, “until”: “2024-01-01T00:00:00+09:00” } 引数(時刻範囲) 移行システム 旧システムDB 新システムDB 変換して挿入・更新 時刻範囲のデータを取得
Slide 27
Slide 27 text
分割移行 ● 少しずつ移行する期間を詰めていって、最後は メンテナンス当日に移行 ○ 例: 2014年から5年分, 次の3年分, 1年分... ○ サービス成長に伴って単位時間あたりのデータ量 が増えていく 27
Slide 28
Slide 28 text
分割移行 ● 期間を詰めるほど移行時間が短くなる、ではない ○ Fargateの立ち上げオーバーヘッドだったり ○ 中間状態を管理するためのS3の読み書きだったり ○ どこかで頭打ちになる ● メンテナンス前の最後の分割移行はちょうどよい 塩梅を狙ってタイミングを設定 28
Slide 29
Slide 29 text
うまくいくのか? ● データの依存関係を丁寧になぞれば可能 ○ 2014-01-01〜2015-01-01のユーザアカウント ○ 2014-01-01〜2015-01-01のコイン ○ 2014-01-01〜2015-01-01の読み物購入情報 ■ 購入情報にはどのコインで買ったか記録される ○ 関連がないデータは並行で移行可能 29
Slide 30
Slide 30 text
うまくいくのか? ● 実装をミスると容易に整合性が破壊される ○ 練習用の環境で走行したら実際に壊れた ■ データの更新に失敗したり ■ 更新すべきところで新規に挿入してしまったり ○ 自動検証を仕込むことに ■ この話は後ほど 30
Slide 31
Slide 31 text
分割移行を実現するために必要な条件 ● 移行元に作成日と更新日が仕込まれていること ● 移行元にレコードを物理削除する処理がないこと 31
Slide 32
Slide 32 text
分割移行を実現するために必要な条件 ● 移行元に作成日と更新日が仕込まれていること ● 更新日だけではダメなケース ■ ユーザの最終更新は2024-02-01 ■ コインの最終更新は2023-01-01 ■ 移行範囲は2023-12-31いっぱい ■ →更新日だけでは依存ユーザが作られない! 32
Slide 33
Slide 33 text
分割移行を実現するために必要な条件 ● 移行元にレコードを物理削除する処理がないこと ○ とはいえ、ありますよね ● あった場合は? 33
Slide 34
Slide 34 text
移行元に物理削除があったら ● 移行元で物理削除を記録してもらう ○ triggerなりアプリケーションで仕込むなり ● 移行先に移行ログをとっておく ○ どのテーブルのどのidがどこに移行されたか ● 移行処理の最初に消す ○ 削除ログがある=元のデータは既にない 34
Slide 35
Slide 35 text
移行ログは便利 ● あとから何をどう移行したか調査しやすい ● 依存するデータがあるときはここから引ける ● 処理をべき等にするためにも利用できる ● INSERTするレコード数が単純計算で2倍にはなるが 35
Slide 36
Slide 36 text
ところで…… ● 素朴にオンラインのまま分割移行すると 移行先のDBにユーザのデータが増える ● ユーザにデータが見えるのでは……? 36
Slide 37
Slide 37 text
オンラインのまま移行す るテクニックふたつ 37
Slide 38
Slide 38 text
分ける・隠す 38
Slide 39
Slide 39 text
分ける ● もともとなかった機能に対しての移行ならユーザに 見えない ● 一見同じ機能でも新機能扱いにしてしまう手 39
Slide 40
Slide 40 text
分ける ● ユーザの利便性を損わないとかビジネス上問題が ないとかで判断されるべきではある ● 例: Web用コインとアプリ用コインを分ける ○ (移行都合ではなく、新システムにおける扱いを 検討する際にたまたま分けていた) ○ 今回は移行都合で意図的に分けた例はない 40
Slide 41
Slide 41 text
隠す ● 素直にやるならこっち ○ フラグを立ててリリースまで隠す ● 例: レンタル状態はWebとアプリで統合したい ○ レンタル状態のテーブルにフラグのカラムを追加 ○ リリースまではWebでアプリのものを表示しない 41
Slide 42
Slide 42 text
…という方針を 立てるためには? 42
Slide 43
Slide 43 text
うまくやるには 43
Slide 44
Slide 44 text
うまくやるには ● 最初から理想に至るのは無理 ● どうする? ○ 仕様を読み込む ○ 本番データの傾向を観察する ○ イテレーションを回す 44
Slide 45
Slide 45 text
仕様を読み込む ● 移行の処理自体はモデリングを翻訳する作業 ● 元の処理がどうなっているか分からないと困る ○ 今回は仕様書とデータ一式をいただいた ● 仕様だけじゃなく実際にアプリを触るのも重要 ○ ユーザが触れる面の全てを把握しておく ○ ユーザ=エンドユーザに限らず運用者なども含む 45
Slide 46
Slide 46 text
本番データの傾向を観察する ● どうあがいても例外的なデータは発生する ○ 運用上発生したり ○ 不具合への対応だったり ● 例外的なデータは仕様や開発データを見ていても 気付けない 46
Slide 47
Slide 47 text
本番データの傾向を観察する ● 気付けない例: ○ 仕様にはないけどNullableでNULLが入っている ○ idが指し示す先のデータがない ● どう移行されるのが正しいのか? を考えるためには データを見つつ仕様を読み込む必要がある ○ 考古学 47
Slide 48
Slide 48 text
イテレーションを回す ● 未完成でもとにかくイテレーションを回す ● 1回実行してうまくいくことは絶対にない ○ なんなら時間の見積もりですら実装やデータの 状況によって変わっていく ● エラーを1回で出し切れることも絶対にない ○ エラーを潰すと依存していた処理でエラーが発生 48
Slide 49
Slide 49 text
イテレーションを回す ● イテレーションを回しやすくする ○ 全量の移行を実施すると時間がかかりすぎる ○ 一部ユーザだけ移行して動作確認しやすいような 仕組みを導入 49
Slide 50
Slide 50 text
イテレーションを回す ● イテレーションを回す障害を取り除く ○ Step Functionsは一箇所で異常終了すると ステートマシン全体が止まる ○ 例外的なデータでいちいち止めていたら処理が 一生終わらない 50
Slide 51
Slide 51 text
イテレーションを回す ● イテレーションを回す障害を取り除く ○ 1イテレーションの中ではエラーがあっても途中 で止めずに最後にエラーが起きたかどうか判断 ○ 個別の処理ではエラーを記録するだけにしつつ エラーがなかったように振る舞う 51
Slide 52
Slide 52 text
ということを意識して 移行の仕組みを作ると よいのでは 52
Slide 53
Slide 53 text
ここまでのまとめ ● 分割移行でメンテナンスウィンドウを短くした ○ 19時間のメンテナンスのうちデータ移行は6時間 ● オンラインのまま移行するためのテクニック ○ データを分ける・隠す ● うまくやるためには ○ 結局は泥臭く・丁寧にやる、以上のことはない 53