ゼロダウンタイム展開-移行Dbスキーマ


14

ゼロダウンタイムの展開の実現には同じ問題が関係していましたが、検討している戦略に関するアドバイスが必要です。

環境

サーバー側の処理にApache / PHPを使用し、永続性にMySQL DB / filesystemを使用する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. この程度の安定性を提供する一方で、ダウンタイムなしで更新を許可するより簡単な方法はありますか?また、スキーマの下位互換性に縛られることを望まないため、「進化的な」スキーマ戦略を避けることも推奨されます。

回答:


4

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

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

プロダクションワン

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

プロダクション2

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

本番DR

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

ライブ配信

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

データ移行

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

結論

リリースイベントを完全に完了すると、Production Twoがプライマリになり、次の展開サイクルのためにProduction Oneに次のリリースをインストールする作業を開始します。

欠点

これは複雑な環境設定であり、大量のシステムリソースを必要とします。多くの場合、システムリソースの2〜3倍の時間が必要です。この方法での操作は、特に非常に大規模で使用頻度の高いシステムがある場合、高価になる可能性があります。


したがって、私が正しく理解している場合、Dbがまだ使用されている間に適用される「一時的な」DBスキーマの変更の代わりに、Db-Bは新しいスキーマに更新され、Db-Bは新しいスキーマに更新されることをお勧めしますスキーマ。更新プログラムのリリース準備が整うと、Webサーバーが切り替えられ、更新プログラムの準備中にDb Aに書き込まれたデータがDb Bに移行されます(特定のタイムスタンプ後にすべての変更を適用することにより)。
マービン

@PeterScottわかった。古いシステムですべてのアクティブセッションが終了し、すべてのDNSキャッシュが新しいCNAMEまたはIPアドレスに更新されるのに十分な時間が経過するまで、スクリプトを実行したくないことに注意してください。
maple_shaft

1
私はそれらの両方の点で大丈夫でなければなりません。セッションが特定の仮想マシンに結び付けられるのを避けるために、サーバーストレージではなくDbにセッションが保持されています。現在、非DNSベースのロードバランサーを使用しようとしています。データセンターレベルの冗長性はありませんが、アプリケーションの起動後1年ほど待つことができます。
マービン

2

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

トランザクションテーブルでは、正確性を保証するために、正規化されたテーブルに対して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番目のデータベースが復旧したときに再適用されません。


1
簿記との比較が好きです。したがって、理解していれば、トランザクションテーブルを使用すると、特定の正規化されたテーブルへのデータの書き込みに非常に小さな遅延を設定できるため、変更の途中で中断するリスクなしにすべてのスキーマ変更を適用できますか?次に、テーブルのスキーマが最新の状態で、非正規化されたトランザクションを正規化されたテーブルに適用するプロセスを再開できます(このプロセスは古いスキーマデータクエリを新しいスキーマにマッピングできます)。
マービン

1
はい。古いデータと新しいデータの両方に対応するために、マッピングストアドプロシージャ(または何でも)を変更します。新しいNOT-NULL列には、「ユーザーの更新時にこれを要求する」ことを意味するコードを古いデータから入力できます。分割する列(つまり、FULLNAMEをFIRSTとLASTに分割する)には、何らかのアルゴリズムが必要です。今後の新しいビジネス要件のために、1つ以上の「コメントのような」列をテーブルに追加することをお勧めします。そうしないと、ユーザーがその目的のために他の列を使用することを保証し、データの修正はほとんど不可能になります。
DocSalvager

古いスキーマ用に構造化されたSELECTクエリが新しいスキーマに適用されるのをどのように防ぎますか?テーブルビューを作成してスキーマテーブルの名前を(スキーマバージョン番号を使用して)変更することもできますが、スキーマの変更は正規化されたテーブルに直接適用されるため、スキーマの変更が適用されている間は問題が残ります。
マービン

1
テーブル、列、その他をRDBMSに追加すると、実際には、RDBMSエンジンのみが書き込むことができる一連の内部テーブルに行を追加するだけです。DBAは、VIEWを介してデータベースを照会することにより、データベースを管理します。Oracle、IBM、MSなどが専門家であり、これが最良の方法であると言うので、我々は彼らのリードに従う必要があるようです。アプリケーションのバージョンごとに一連のVIEWを作成します。開発者が作成する(通常はかなり非正規化された)テーブルの後にモデルを作成して、破損したデータを防ぐために適切に正規化できます。
DocSalvager

ありがとう。これについて考える必要があります。メインドメインからすべての状態保持ロジックを完全に削除するORM層をアプリケーションに構築しています。サーバー側のプログラミングに基づいているため、DB管理側よりもその側から問題を解決する傾向があります。私の現在の戦略を使用すると、DbはORMがrawテーブルをアクティブに管理することで非常にフラットになります。テーブルビューと、場合によってはトランザクションログを追加すると、ORMがさらに複雑になりますが、データの分裂を伴わずに複数のスキーマバージョンをサポートできます。
マービン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.