web-dev-qa-db-ja.com

ダウンタイムなしの導入-移行DBスキーマ

ゼロダウンタイムデプロイメントの実現 同じ問題に触れましたが、検討している戦略についてアドバイスが必要です。

環境

サーバーサイド処理用のApache/PHPと永続化用のMySQL DB /ファイルシステムを備えたWebベースのアプリケーション。

現在、インフラストラクチャを構築しています。すべてのネットワークハードウェアに冗長性があり、すべての主要なネットワークケーブルがフォールトトレランスのためにボンディングペアで使用されます。サーバーは、ハードウェアのフォールトトレランス用の高可用性ペアとして構成されており、仮想マシンのフォールトトレランスと一般的なパフォーマンスの両方に対して負荷分散されます。

ダウンタイムなしでアプリケーションに更新を適用できることが私の意図です。 100%の稼働時間を確保できるようにインフラストラクチャを設計するときは、非常に苦労しました。更新が適用されるたびに10〜15分のダウンタイムが発生するのは非常に残念です。これは、非常に迅速なリリースサイクルを予定しているため、特に重要です(1日あたり1つ以上のリリースに達する場合があります)。

ネットワークトポロジー

これはネットワークの要約です:

                      Load Balancer
             |----------------------------|
              /       /         \       \  
             /       /           \       \ 
 | Web Server |  DB Server | Web Server |  DB Server |
 |-------------------------|-------------------------|
 |   Host-1   |   Host-2   |   Host-1   |   Host-2   |
 |-------------------------|-------------------------|
            Node A        \ /        Node B
              |            /            |
              |           / \           |
   |---------------------|   |---------------------|
           Switch 1                  Switch 2

   And onward to VRRP enabled routers and the internet

注:DBサーバーはマスター/マスターレプリケーションを使用します

推奨される戦略

これを達成するために、私は現在、DBスキーマのアップグレードスクリプトを2つの部分に分割することを考えています。アップグレードは次のようになります。

  1. ノードAのWebサーバーはオフラインになります。トラフィックは引き続きノードBのWebサーバーによって処理されます。
  2. 移行スキーマの変更がDBサーバーに適用されます
  3. Webサーバーコードベースが更新され、キャッシュがクリアされ、その他のアップグレードアクションが実行されます。
  4. WebサーバーAがオンラインになり、WebサーバーBがオフラインになります。
  5. WebサーバーBコードベースが更新され、キャッシュがクリアされ、その他のアップグレードアクションが実行されます。
  6. WebサーバーBがオンラインになります。
  7. 最終的なスキーマ変更がDBに適用されます

「移行スキーマ」は、バージョン間の互換性のあるDBを確立するように設計されます。これは主に、テーブル自体が新しいスキーマに変更される一方で、古いバージョンのスキーマをシミュレートするテーブルビューを利用します。これにより、旧バージョンが通常どおりDBと対話できるようになります。テーブル名にはスキーマのバージョン番号が含まれ、どのテーブルに書き込むかについて混乱が生じないようにします。

「最終スキーマ」は、下位互換性を削除し、スキーマを整頓します。

質問

要するに、これはうまくいくのでしょうか?

すなわち:

  1. 移行スキーマの変更の特定の時点で同時書き込みが発生する可能性があるため、問題は発生しますか?テーブルを変更して下位互換性のあるビューを作成するクエリのグループが確実に連続して実行されるようにする方法はありますか?つまり、スキーマの変更が完了するまでバッファに保持されている他のクエリを使用します。これは通常、ミリ秒だけです。

  2. この程度の安定性を提供すると同時に、ダウンタイムなしで更新を可能にする簡単な方法はありますか?また、スキーマの下位互換性に縛られたくないので、「進化的な」スキーマ戦略を回避することもお勧めします。

14
Marvin

あなたが本当に探しているのは、必要なほど高可用性ではないようです 継続的可用性

基本的には計画は機能しますが、セットアップの主な欠陥は、リリースでのデータベーススキーマの変更により、ダウンタイムが発生したり、まだ利用可能なノードが正常に動作しなくなったりする可能性があることです。継続的可用性アプローチは、本質的に多数の本番環境を作成することでこれを解決します。

プロダクションワン

この環境は、ユーザーが使用しているソフトウェアの現在のライブバージョンです。独自のWebサーバー、アプリケーションサーバー、およびデータベースサーバーとテーブルスペースがあります。他の環境から独立して動作します。これらのサービスのドメイン解決エンドポイントを所有するロードバランサーは、現在これらのWebサーバーを指しています。

プロダクション2

これは基本的に、Production Oneと同じリリースステージング環境です。ここでリリースアップグレードを実行し、ライブイベントの前に健全性テストを行うことができます。これにより、この環境でデータベースの変更を安全に実行することもできます。現在、ロードバランサーはこの環境を指していません。

生産DR

これは、世界の別の地域にある別のデータセンターの別の複製です。これにより、ロードバランサーでDNSスイッチを実行することにより、壊滅的なイベントの発生時にフェイルオーバーできます。

公開する

このイベントは基本的にDNSレコードを更新して、プロダクション1からプロダクション2に、またはその逆に循環させます。これは世界中のDNSサーバー全体に伝播するのにしばらく時間がかかるため、しばらくの間両方の環境を稼働させたままにします。一部のユーザーは、古いバージョンのソフトウェアの既存のセッションで作業している場合があります。ほとんどのユーザーは、ソフトウェアのアップグレードバージョンで新しいセッションを確立します。

データ移行

ここでの唯一の欠点は、その時間帯のすべてのデータをその時点ですべてのユーザーが利用できるわけではないことです。以前のバージョンのデータベースには、重要なユーザーデータがあり、新しいデータベーススキーマに安全に移行する必要があります。これは、十分にテストされたデータのエクスポートと移行のスクリプト、バッチジョブ、または同様のETLプロセスで実現できます。

結論

リリースイベントを完全に完了すると、プロダクション2がメインになり、次のリリースをプロダクション1にインストールして次のデプロイメントサイクルに取り掛かります。

欠点

これは複雑な環境設定であり、多くの場合、正常に実行するにはシステムリソースの2〜3倍の大量のシステムリソースが必要です。この方法での運用は、特に非常に大規模で大量のシステムを使用している場合は、コストがかかる可能性があります。

4
maple_shaft

あなたの戦略は健全です。 「移行スキーマ」を「トランザクションテーブル」の完全なセットに拡張することを検討することだけを提案します。

トランザクションテーブルでは、正確さを保証するために、正規化されたテーブルに対してSELECT(クエリ)が実行されます。ただし、すべてのデータベースのINSERT、UPDATE、DELETEは常に非正規化トランザクションテーブルに書き込まれます。

次に、別個の並行プロセスが、確立されたビジネスルールとスキーマ要件に従って正規化されたテーブルに(おそらくストアドプロシージャを使用して)それらの変更を適用します。

ほとんどの場合、これはほぼ瞬時に行われます。ただし、アクションを分離することで、システムは過剰なアクティビティとスキーマ更新の遅延に対応できます。

データベース(B)のスキーマの変更中に、アクティブデータベース(A)のデータ更新はトランザクションテーブルに入り、正規化されたテーブルにすぐに適用されます。

データベース(B)を元に戻すと、(A)のトランザクションが(B)のトランザクションテーブルに書き込まれることにより、データベースに適用されます。その部分が完了したら、(A)を停止し、スキーマの変更をそこに適用できます。 (B)は(A)からのトランザクションの適用を終了すると同時に、(A)と同じようにキューに入れられるライブトランザクションも処理し、「ライブトランザクション」は(A)が戻ったときと同じ方法で適用されます。

トランザクションテーブルの行は次のようになります...

| ROWID | TRANSNR | DB | TABLE | SQL STATEMENT
    0        0       A    Name   INSERT INTO Name ...
    1        0       A    Addr   INSERT INTO Addr ...
    2        0       A    Phone  INSERT INTO Phone ...
    3        1       A    Stats   UPDATE Stats SET NrOfUsers=...

トランザクションの「テーブル」は、パフォーマンス要件に応じて、実際には別のNoSQLデータベースの行またはシーケンシャルファイルでさえあります。ボーナスは、アプリケーション(この場合はWebサイト)のコーディングがトランザクションテーブルにのみ書き込むため、少し単純になることです。

このアイデアは、複式簿記と同じ原則に従いますが、同様の理由があります。

トランザクションテーブルは、簿記の「ジャーナル」に似ています。完全に正規化されたテーブルは、簿記の「元帳」に類似しており、各テーブルは簿記の「口座」のようなものです。

簿記では、各トランザクションはジャーナルで2つのエントリを取得します。 1つは「借方」の元帳勘定用で、もう1つは「貸方」勘定用です。

RDBMSでは、「ジャーナル」(トランザクションテーブル)は、そのトランザクションによって変更される各正規化テーブルのエントリを取得します。

上の表の図のDB列は、トランザクションが発生したデータベースを示しているため、他のデータベースのキューに入れられた行をフィルターで除外し、2番目のデータベースが復旧したときに再適用することはできません。

2
DocSalvager