ゼロダウンタイム展開の実現


40

停止時間ゼロの展開を達成しようとしているので、理論的には、営業時間外に少なく、「遅い」時間にもっと多く展開できます。

私の現在のセットアップ、やや単純化された:

  • WebサーバーA(.NETアプリ)
  • WebサーバーB(.NETアプリ)
  • データベースサーバー(SQL Server)

私の現在の展開プロセス:

  1. WebサーバーAとBの両方のサイトを「停止」する
  2. デプロイされているアプリのバージョンのデータベーススキーマをアップグレードする
  3. WebサーバーAを更新する
  4. WebサーバーBを更新する
  5. すべてをオンラインに戻す

現在の問題

これにより、毎月わずかなダウンタイムが発生します(約30分)。私は休み時間にこれを行うので、それは大きな問題ではありません-しかし、それは私が逃げたいものです。

また-実際に「戻る」方法はありません。通常、ロールバックDBスクリプトは作成せず、スクリプトのみをアップグレードします。

ロードバランサーの活用

一度に1つのWebサーバーをアップグレードできるようになりたいです。WebサーバーAをロードバランサーから取り出してアップグレードし、オンラインに戻し、WebサーバーBについて繰り返します。

問題はデータベースです。私のソフトウェアの各バージョンは、異なるバージョンのデータベースに対して実行する必要があります-だから私は一種の「スタック」です。

可能な解決策

私が検討している現在の解決策は、次のルールを採用しています:

  • データベーステーブルを削除しないでください。
  • データベース列を削除しないでください。
  • データベース列の名前を変更しないでください。
  • 列を並べ替えないでください。
  • すべてのストアドプロシージャはバージョン管理する必要があります。
    • 意味-「spFindAllThings」は、編集時に「spFindAllThings_2」になります。
    • その後、再度編集すると「spFindAllThings_3」になります。
    • 同じルールがビューに適用されます。

一方、これは少し極端に思えます-私はそれが問題を解決すると思います。アプリケーションの各バージョンは、中断することなくDBにヒットします。コードは、ビュー/ストアドプロシージャから特定の結果を予期します。これにより、その「契約」が有効になります。問題は、それがただずさんに染み込んでいるということです。アプリがしばらく展開された後、古いストアドプロシージャをクリーンアップできることは知っていますが、それは単に汚い感じです。また、これはこれらのルールに従っているすべての開発者に依存しますが、ほとんどの場合これは起こりますが、誰かが間違いを犯すと思います。

最後に-私の質問

  • これはずさんですか、それともハックですか?
  • 他の誰かがこれをやっていますか?
  • 他の人はこの問題をどのように解決していますか?

2
バックアウト計画はどこにありますか?すべてが機能し、回帰がないことをどのようにテストしますか?
鹿ハンター

3
「決して」は必要ありません。隣接する2つのバージョンがすべて同時に実行できることを「必要」にするだけです。これにより、アップグレードパスが制限されますが、DBスキーマを大幅に変更できないほど深刻ではありません。
ヨアヒムザウアー

Joachimに感謝します...基本的な考え方が明確になるように絶対的な話をするのが好きです。しかし、あなたは正しいです。Nリリースによって後方互換性があるというポリシーがあり、その時点で不要なDBオブジェクトを削除できます。
MattW

2
適切なロールバック計画が必要になります。いつかそれが必要になります。
するThorbjörnRavnアンデルセン

1
私の経験では、ほとんどのウェブサイトでは、解決策は解決する問題よりも悪いです。それが追加する複雑さは、現在予想できるよりも高くなります。おそらく、変更を加えたり機能を追加したりするための時間/労力が何倍もかかるでしょう。私は絶対にできませんウェブサイトのためにそれを検討したい任意の、ダウンタイムを持っている、これまで
MGOwen

回答:


14

これは、データベースを使用したソフトウェアアップグレードに対する非常に実用的なアプローチです。それはして説明した 2003年にMartin Fowler氏とPramodさんSadalageによって、その後にまで書かれたリファクタリングデータベース:進化データベースの設計

私はあなたがそれがずさんだと言うとき、あなたが何を意味するかを見ることができますが、意図的かつ先見の明をもって行われ、明らかに使用されなくなったコードベースとデータベースから未使用の構造をリファクタリングする時間を取ると、それははるかに堅牢ですアップグレードおよびロールバックスクリプトに基づくよりシンプルなソリューション。


5

「ゼロダウンタイム」は、この種のアプローチの多くの考えられる理由の1つにすぎません。このようにデータモデルの下位互換性を維持すると、さまざまな問題に対処するのに役立ちます。

  • データベースにアクセスするソフトウェアパッケージが多数ある場合、スキーマの変更がそれらに影響を与える場合、それらすべてをチェックする必要はありません(同じデータベースにアクセスするプログラムを複数のチームが記述している大規模な組織では、スキーマの変更は非常に困難になる場合があります)

  • 必要に応じて、プログラムの古いバージョンをチェックアウトすると、新しいデータベースで再実行される可能性が高くなります(古いプログラムが新しい列を正しく処理することを期待しない限り)

  • アーカイブデータの現在のデータベースバージョンへのインポート/エクスポートがはるかに簡単

リストの追加ルールは次のとおりです

  • 新しい各列は、NULL可能か、意味のあるデフォルト値を提供する必要があります。

(これにより、新しい列を知らない古いプログラムでさえ、データベースに新しいレコードを作成するときに何も壊れないことが保証されます)。

もちろん、このアプローチには1つの重大な欠点があります。データモデルの品質は時間とともに低下する可能性があります。また、データベースにアクセスするすべてのアプリケーションを完全に制御でき、たとえば列の名前を変更するときにこれらすべてのアプリケーションを簡単にリファクタリングできる場合は、よりクリーンな方法でリファクタリングすることを検討できます。


4

展開ごとに異なります。

もちろん、テーブルや列を削除することはできません。インターフェイスの互換性を壊したものを変更することはできません。いつでも抽象化のレイヤーを追加できます。ただし、その抽象化とバージョン管理をバージョン管理する必要があります。

自問する必要のある質問は、すべてのリリースが、後方互換性のない方法でスキーマを変更するかどうかです。

そのようにスキーマを変更するリリースが非常に少ない場合、データベースの問題はミュートになります。アプリケーションサーバーをローリングデプロイするだけです。

ダウンタイムが最小限の展開で最も役立つ2つのことは次のとおりです。

  1. 後方互換性を目指して-少なくとも1つのリリース内で。常に達成できるとは限りませんが、特に各リリースが小さい場合は、リリースの90%以上で達成できると確信しています。
  2. プレリリースおよびポストリリースのデータベーススクリプトを用意します。これにより、アプリコードをデプロイする前に新しいオブジェクトを作成し、アプリコードのデプロイ後に古いオブジェクトを削除することで、名前の変更やインターフェースの変更を処理できます。null不可の新しい列を追加する場合、プレリリーススクリプトでデフォルト値を満たすトリガーを使用してnull可能として追加できます。その後、ポストリリースでトリガーをドロップできます。

メンテナンスウィンドウのために、展開の残りを保存できることを願っています。

ダウンタイムを必要とする少数のデプロイの処理に役立つ可能性のある他のアイデア:

  • コードに後方互換性を構築できますか?たとえば、コードで複数のタイプの結果セットをサポートできる方法はありますか?列をintからdoubleに変更する必要がある場合、アプリのコードはそれを文字列として読み取り、解析できます。一種のハックですが、リリースプロセスを経験するための一時的なコードであれば、それは世界の終わりではないかもしれません。
  • ストアドプロシージャは、スキーマの変更からアプリコードを隔離するのに役立ちます。これはここまでしかできませんが、少し役立ちます。

2

少し手間をかけると、このように実行できる可能性があります。

  1. エクスポートしてデータベースをバックアップする
  2. バックアップをインポートしますが、myDb_2_1などのリリースバージョンに名前を変更します
  3. myDB_2_1でデータベースリリースを実行する
  4. WebサーバーAのアプリプールを「停止」するか、ロードバランサーから取り出します
  5. WebサーバーAを更新し、実装後テストを実行し、必要に応じてロールバックします
  6. セッションはWebサーバーBをブリードし、WebサーバーAをループに戻します
  7. WebサーバーBをアップグレードしてからロードバランサーに戻す

当然、Web更新では、新しいDbスキーマを指す新しい構成エントリが必要になります。毎月1回リリースを行っており、小規模なチームの場合、後方互換性のないDBの変更を実際にいくつ行っているのでしょうか。テストによってそれを制御できる場合、ダウンタイムなしで、または最悪の場合わずか5分のダウンタイムで自動展開を取得できます。


1
バックアップを保存した後、サーバーAを停止する前に、サーバーAのアプリがそのDBに書き込む場合はどうなりますか?常に「脆弱性の窓」があります。これらの書き込みは失われ、受け入れられない場合があります。
-sleske
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.