Déploiement sans interruption de service - Schéma Db transitionnel

14

Atteindre un déploiement sans interruption de service a touché le même problème, mais j'ai besoin de conseils sur une stratégie que j'envisage.

Le contexte

Une application Web avec Apache / PHP pour le traitement côté serveur et le système de fichiers / base de données MySQL pour la persistance.

Nous construisons actuellement l'infrastructure. Tout le matériel de mise en réseau aura une redondance et tous les câbles réseau principaux seront utilisés par paires liées pour la tolérance aux pannes. Les serveurs sont configurés en tant que paires à haute disponibilité pour la tolérance aux pannes matérielles et seront équilibrés en charge pour la tolérance aux pannes des machines virtuelles et les performances générales.

J'ai l'intention de pouvoir appliquer des mises à jour à l'application sans aucun temps d'arrêt. J'ai pris grand soin lors de la conception de l'infrastructure pour m'assurer que je peux fournir une disponibilité à 100%; il serait extrêmement décevant de disposer de 10 à 15 minutes d'interruption à chaque application d'une mise à jour. Ceci est particulièrement important car nous avons l'intention d'avoir un cycle de libération très rapide (il peut parfois atteindre une ou plusieurs versions par jour.

Topologie du réseau

Voici un résumé du réseau:

                      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

Remarque: les serveurs de base de données utilisent la réplication maître-maître

Stratégie suggérée

Pour y parvenir, je pense actuellement à diviser les scripts de mise à niveau du schéma DB en deux parties. La mise à niveau ressemblerait à ceci:

  1. Le serveur Web sur le nœud A est mis hors ligne; le trafic continue d'être traité par le serveur Web sur le nœud B.
  2. Les modifications du schéma de transition sont appliquées aux serveurs de base de données
  3. Serveur Web Une base de code est mise à jour, les caches sont effacés et toute autre action de mise à niveau est effectuée.
  4. Le serveur Web A est mis en ligne et le serveur Web B est mis hors ligne.
  5. La base de code du serveur Web B est mise à jour, les caches sont effacés et toute autre action de mise à niveau est effectuée.
  6. Le serveur Web B est mis en ligne.
  7. Les modifications du schéma final sont appliquées à DB

Le «schéma transitoire» serait conçu pour établir une base de données compatible entre versions. Cela utiliserait principalement des vues de table qui simulent l'ancien schéma de version tandis que la table elle-même serait modifiée pour le nouveau schéma. Cela permet à l'ancienne version d'interagir avec la base de données comme d'habitude. Les noms de table incluraient des numéros de version de schéma pour garantir qu'il n'y aura pas de confusion sur la table dans laquelle écrire.

«Schéma final» supprimerait la compatibilité descendante et rangerait le schéma.

Question

En bref, cela fonctionnera-t-il?

plus précisement:

  1. Y aura-t-il des problèmes en raison de la possibilité d'écritures simultanées au point spécifique du changement de schéma de transition? Existe-t-il un moyen de s'assurer que le groupe de requêtes qui modifient la table et créent la vue rétrocompatible sont exécutées consécutivement? c'est-à-dire avec toutes les autres requêtes conservées dans le tampon jusqu'à ce que les modifications de schéma soient terminées, qui ne seront généralement que des millisecondes.

  2. Existe-t-il des méthodes plus simples qui offrent ce degré de stabilité tout en permettant également des mises à jour sans temps d'arrêt? Il est également préférable d'éviter la stratégie de schéma «évolutif» car je ne souhaite pas rester enfermé dans la compatibilité de schéma en arrière.

Marvin
la source

Réponses:

4

Il semble que ce que vous recherchez n'est pas tant la haute disponibilité que la disponibilité continue .

Essentiellement, votre plan fonctionnera, mais vous semblez avoir remarqué que le principal défaut de votre configuration est que les modifications du schéma de base de données dans une version peuvent entraîner un temps d'arrêt ou une défaillance du nœud encore disponible pour fonctionner correctement. L'approche de disponibilité continue résout ce problème en créant essentiellement un certain nombre d'environnements de production.

Production One

Cet environnement est votre version actuelle du logiciel utilisé par les utilisateurs. Il possède ses propres serveurs Web, serveurs d'applications, serveurs de base de données et tablespace. Il fonctionne indépendamment de tout autre environnement. L'équilibreur de charge qui possède le point de terminaison de résolution de domaine pour ces services pointe actuellement vers ces serveurs Web.

Production deux

Il s'agit essentiellement d'un environnement de mise en production identique à Production One. Vous pouvez effectuer vos mises à niveau de version ici et faire vos tests d'intégrité avant votre événement en direct. Cela vous permet également d'effectuer en toute sécurité vos modifications de base de données sur cet environnement. L'équilibreur de charge ne pointe pas vers cet environnement actuellement.

Production DR

Il s'agit d'un autre doublon dans un centre de données distinct situé dans une autre région du monde. Cela vous permet de basculer en cas d'événement catastrophique en effectuant un commutateur DNS sur l'équilibreur de charge.

Go Live

Cet événement met essentiellement à jour l'enregistrement DNS pour passer de Production One à Production One ou vice versa. Cela prend un certain temps pour se propager à travers les serveurs DNS du monde, donc vous laissez les deux environnements en cours d'exécution pendant un certain temps. Certains utilisateurs PEUVENT travailler dans des sessions existantes sur l'ancienne version de votre logiciel. La plupart des utilisateurs établiront de nouvelles sessions sur la version mise à niveau de votre logiciel.

Migration de données

Le seul inconvénient ici est que toutes les données de cette fenêtre ne sont pas disponibles pour tous les utilisateurs à ce moment-là. Il y a clairement des données utilisateur importantes dans la base de données de la version précédente qui doivent maintenant être migrées en toute sécurité vers le nouveau schéma de base de données. Cela peut être accompli avec un script d'exportation et de migration de données bien testé ou un travail par lots ou un processus ETL similaire.

Conclusion

Une fois que vous avez terminé votre événement de version, Production Two est maintenant votre principal et vous commencez à travailler sur l'installation de la prochaine version de Production One pour le prochain cycle de déploiement.

Désavantages

Il s'agit d'une configuration d'environnement complexe qui nécessite une grande quantité de ressources système, souvent deux à trois fois plus de ressources système pour réussir. Le fonctionnement de cette façon peut être coûteux, surtout si vous avez de très gros systèmes à usage intensif.

maple_shaft
la source
Donc, si j'ai bien compris, vous suggérez qu'au lieu d'un changement de schéma DB «transitoire» qui est appliqué pendant que le Db est encore en cours d'utilisation, Db-A est maintenu en ligne avec l'ancien schéma tandis que Db-B est mis à jour vers le nouveau schéma. Lorsque la mise à jour est prête à être publiée, les serveurs Web sont modifiés et les données qui ont été écrites sur Db A pendant la préparation de la mise à jour sont migrées vers Db B (probablement en appliquant toutes les modifications après un horodatage spécifique).
Marvin
@PeterScott Vous l'avez compris. Gardez à l'esprit que vous ne voulez pas exécuter le script tant que vous n'êtes pas sûr que toutes les sessions actives sont terminées dans l'ancien système et que cela fait suffisamment longtemps que tous les caches DNS ont été mis à jour vers la nouvelle adresse CNAME ou IP.
maple_shaft
1
Je devrais être d'accord sur ces deux points; les sessions sont conservées dans la base de données plutôt que dans le stockage du serveur pour éviter que les sessions soient liées à des machines virtuelles spécifiques et j'ai actuellement l'intention d'essayer d'utiliser un équilibreur de charge non DNS. Je n'aurai pas de redondance au niveau du centre de données, mais cela peut attendre environ un an après le lancement de l'application.
Marvin
2

Votre stratégie est solide. Je proposerais seulement d'envisager d'élargir le "schéma de transition" en un ensemble complet de "tables de transactions".

Avec les tables de transactions, les SELECT (requêtes) sont effectuées par rapport aux tables normalisées afin d'assurer l'exactitude. Mais tous les INSERT, UPDATE et DELETE de la base de données sont toujours écrits dans les tables de transactions dénormalisées.

Ensuite, un processus distinct et simultané applique ces modifications (peut-être à l'aide de procédures stockées) aux tables normalisées conformément aux règles métier et aux exigences de schéma établies.

La plupart du temps, cela serait pratiquement instantané. Mais la séparation des actions permet au système de gérer une activité excessive et des retards de mise à jour de schéma.

Lors des modifications de schéma sur la base de données (B), les mises à jour des données sur la base de données active (A) iraient dans ses tables de transactions et seraient immédiatement appliquées à ses tables normalisées.

Lors de la sauvegarde de la base de données (B), les transactions de (A) lui seraient appliquées en les écrivant dans les tables de transactions de (B). Une fois cette partie terminée, (A) pourrait être supprimé et les modifications de schéma y appliquées. (B) terminerait d'appliquer les transactions de (A) tout en gérant ses transactions en direct qui seraient mises en file d'attente comme (A) et les "live" seraient appliquées de la même manière lorsque (A) reviendrait.

Une ligne de table de transactions pourrait ressembler à quelque chose ...

| 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=...

Les "tables" de transaction peuvent en fait être des lignes dans une base de données NoSQL distincte ou même des fichiers séquentiels, selon les exigences de performances. Un bonus est que le codage de l'application (site Web dans ce cas) devient un peu plus simple car il n'écrit que dans les tables de transactions.

L'idée suit les mêmes principes que la comptabilité en partie double et pour des raisons similaires.

Les tables de transactions sont analogues à un "journal" de comptabilité. Les tables entièrement normalisées sont analogues à un "grand livre" de comptabilité, chaque table étant un peu comme un "compte" de comptabilité.

En comptabilité, chaque transaction obtient deux entrées dans le journal. Un pour le compte du grand livre "débité" et l'autre pour le compte "crédité".

Dans un SGBDR, un "journal" (table de transactions) obtient une entrée pour chaque table normalisée à modifier par cette transaction.

La colonne DB dans l'illustration du tableau ci-dessus indique sur quelle base de données la transaction est née, permettant ainsi aux lignes en file d'attente de l'autre base de données d'être filtrées et non réappliquées lorsque la deuxième base de données est remontée.

DocSalvager
la source
1
J'aime la comparaison avec la comptabilité. Donc, si j'ai bien compris, les tables de transactions me permettent de placer un très petit retard sur l'écriture des données dans une table normalisée particulière afin que je puisse appliquer toutes les modifications de schéma sans risque d'interruption à mi-chemin des modifications? Ensuite, avec le schéma de la table à jour, je peux reprendre le processus qui applique les transactions dénormalisées aux tables normalisées (ce processus étant capable de mapper les anciennes requêtes de données de schéma vers le nouveau schéma)?
Marvin
1
Oui. Vous modifieriez les procédures stockées de mappage (ou autre) pour prendre en charge les anciennes et les nouvelles données. De nouvelles colonnes NOT-NULL peuvent être remplies à partir d'anciennes données avec un code qui signifie «demander ceci lors de la mise à jour de l'utilisateur». Les colonnes à diviser (c'est-à-dire FULLNAME en FIRST et LAST) auraient besoin d'un algorithme. Je recommande d'ajouter une ou plusieurs colonnes "de type commentaire" aux tableaux pour les nouvelles exigences biz qui se présentent. Si vous ne le faites pas, je garantis que les utilisateurs s'approprieront d'autres colonnes à cet effet et la fixation des données sera alors presque impossible.
DocSalvager
Comment empêcheriez-vous les requêtes SELECT structurées pour l'ancien schéma d'être appliquées au nouveau schéma? Je pourrais utiliser créer une vue de table et renommer la table de schéma (avec un numéro de version de schéma) mais cela serait toujours problématique pendant que les modifications de schéma sont appliquées car elles s'appliquent directement à la table normalisée.
Marvin
1
Lorsque vous ajoutez une table, une colonne ou toute autre chose à un SGBDR, vous ajoutez en fait simplement des lignes à un ensemble de tables internes qui ne peuvent être écrites que par le moteur SGBDR. Les administrateurs de base de données gèrent la base de données en les interrogeant via des VIEW. Étant donné qu'Oracle, IBM, MS, etc. sont les experts et disent que c'est la meilleure façon, il semble que nous devrions suivre leur exemple. Créez un ensemble de VUES pour chaque version de l'application. Vous pouvez les modéliser d'après les tables (généralement assez dénormalisées) que les développeurs souhaitent que vous créiez afin de pouvoir les normaliser correctement pour éviter les données corrompues.
DocSalvager
Merci. Je vais devoir y penser. je construis une couche ORM dans l'application qui supprime complètement toute logique de persistance d'état du domaine principal; étant plus basé sur la programmation côté serveur, j'ai tendance à résoudre les problèmes plus de ce côté que du côté de l'administration de la base de données. En utilisant ma stratégie actuelle, le Db serait assez plat avec l'ORM gérant activement les tables brutes. L'ajout de vues de table et, éventuellement, d'un journal des transactions ajoute une plus grande complexité à l'ORM, mais il permet également la prise en charge de plusieurs versions de schéma sans fractionnement des données.
Marvin