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:
- 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.
- Les modifications du schéma de transition sont appliquées aux serveurs de base de données
- Serveur Web Une base de code est mise à jour, les caches sont effacés et toute autre action de mise à niveau est effectuée.
- Le serveur Web A est mis en ligne et le serveur Web B est mis hors ligne.
- 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.
- Le serveur Web B est mis en ligne.
- 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:
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.
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.
la source
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 ...
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.
la source