Mise à jour de la base de données et déploiement sans interruption de service

De nombreux articles ont Ă©tĂ© Ă©crits sur la mise Ă  jour des systĂšmes Ă  la volĂ©e sans les arrĂȘter (dĂ©ploiement sans temps d'arrĂȘt) et de nombreux aspects de cette approche sont assez Ă©vidents. À mon avis, la partie la plus difficile du dĂ©ploiement dans ce cas est la mise Ă  jour des entrepĂŽts de donnĂ©es si leur contrat (schĂ©ma) a changĂ©. C'est cet aspect que je voudrais considĂ©rer dans cet article.

Quelle que soit la base de donnĂ©es - avec un schĂ©ma de donnĂ©es explicite comme relationnel ou arbitraire comme NoSQL - le schĂ©ma de donnĂ©es est toujours prĂ©sent, mĂȘme au niveau de l'application. Les donnĂ©es lues dans la base de donnĂ©es doivent ĂȘtre comprĂ©hensibles pour le client, mĂȘme si le rĂ©fĂ©rentiel lui-mĂȘme n'impose aucune restriction Ă  sa structure.

Supposons qu'un systÚme avec une structure de données spécifique et des téraoctets de données dans la base de données fonctionne déjà en production. Dans la nouvelle version du systÚme, nous devons légÚrement modifier la structure pour implémenter de nouvelles fonctionnalités ou améliorer les performances. Considérez quels changements dans le circuit peuvent se produire:

  • Ajout d'un nouveau champ
  • Suppression de champs
  • Renommer le champ
  • Modifications du type de champ
  • Transfert d'un champ vers une autre structure de donnĂ©es (par exemple, en cas de dĂ©normalisation)

L'ajout d'un nouveau champ ainsi que l'ajout de tout autre objet de base de donnĂ©es est une modification rĂ©trocompatible et ne nĂ©cessite aucune Ă©tape supplĂ©mentaire en termes de mise en Ɠuvre du dĂ©ploiement sans interruption (avec une mise en garde - si ce nouveau champ ou objet ne dĂ©pend pas fonctionnellement des autres dĂ©jĂ  stockĂ©s dans la base de donnĂ©es donnĂ©es). Appliquez simplement les modifications Ă  la base de donnĂ©es Ă  la volĂ©e, puis dĂ©ployez une nouvelle version du code qui utilise les nouveaux objets de base de donnĂ©es.

La suppression d'un champ ou de tout autre objet de base de donnĂ©es n'est pas une modification rĂ©trocompatible, mais l'approche de sa mise en Ɠuvre est trĂšs simple - les objets de base de donnĂ©es inutiles doivent ĂȘtre supprimĂ©s uniquement aprĂšs que la nouvelle version du systĂšme est complĂštement bloquĂ©e.

Les trois autres types de modifications sont plus complexes en termes de dĂ©ploiement sans interruption de service. En gĂ©nĂ©ral, tous peuvent ĂȘtre effectuĂ©s en copiant des donnĂ©es vers d'autres champs / entitĂ©s et en supprimant les «anciens» aprĂšs une migration rĂ©ussie des donnĂ©es: pour renommer, vous pouvez copier les donnĂ©es de l'ancien champ vers un champ avec un nouveau nom, puis supprimer l'ancien champ, changer le type de donnĂ©es peut ĂȘtre fait avec renommer, etc. D'une maniĂšre ou d'une autre, sur une pĂ©riode de temps, la base de donnĂ©es doit prendre en charge les anciens et les nouveaux contrats. Il existe au moins deux façons d'effectuer de telles modifications Ă  la volĂ©e:

Si la base de données prend en charge les déclencheurs


  1. Créez des déclencheurs qui copient les données de l'ancien emplacement vers le nouveau lors de tout changement / ajout et définissez-les en production.
  2. Appliquez un utilitaire de conversion de donnĂ©es qui fait de mĂȘme, mais pour tous les enregistrements de la base de donnĂ©es. Comme les dĂ©clencheurs sont dĂ©jĂ  installĂ©s, l'utilitaire ne peut rien faire de plus compliquĂ© qu'une simple mise Ă  jour «fictive» de chaque enregistrement (UPDATE table SET champ = champ ...). Un point trĂšs important ici est que l'action de lire les donnĂ©es de l'ancien endroit et d'Ă©crire dans le nouveau doit ĂȘtre atomique et protĂ©gĂ©e des changements perdus. Selon la structure de la base de donnĂ©es, vous pouvez utiliser un verrouillage pessimiste via SELECT FOR UPDATE ou ses analogues, ou optimiste si la table a un champ avec une version d'enregistrement.
  3. Une fois que l'utilitaire a terminĂ© son travail (selon la quantitĂ© de donnĂ©es et la complexitĂ© de la mise Ă  jour, le temps d'exĂ©cution peut prendre des jours), il est dĂ©jĂ  possible d'installer une nouvelle version du systĂšme qui prend en charge le nouveau schĂ©ma de donnĂ©es. À ce stade, tous les enregistrements de la base de donnĂ©es qui existaient au moment du lancement de l'utilitaire seront convertis avec succĂšs, et tous les nouveaux qui sont apparus pendant son fonctionnement seront Ă©galement convertis par des dĂ©clencheurs.
  4. Supprimez les déclencheurs et tous les champs (ou autres objets de base de données) qui ne sont plus nécessaires.

S'il n'est pas possible d'utiliser des déclencheurs (comme c'est le cas avec de nombreuses solutions NoSQL)




  1. CrĂ©ez et dĂ©ployez une nouvelle version de l'application (version temporaire 1 sur la figure), qui lit toujours Ă  partir de l'ancien champ, mais lors de l'Ă©criture dans ce champ, elle met Ă  jour Ă  la fois l'ancien et le nouvel emplacement correspondant (dans la figure «C» - l'ancien, «H» - nouveau). Zadeplit cette version sur tous les nƓuds sur lesquels les instances d'application s'exĂ©cutent.
  2. Appliquez un utilitaire qui copie les données de l'ancien emplacement vers le nouveau. Comme pour les déclencheurs, vous devez prendre des mesures pour éviter les modifications perdues.
  3. CrĂ©ez et, une fois l'utilitaire terminĂ©, installez une autre version de l'application (version temporaire 2), qui lit les donnĂ©es d'un nouveau champ, mais Ă©crit toujours Ă  deux endroits. Cette Ă©tape est nĂ©cessaire, car lors de la mise Ă  jour sĂ©quentielle de chacun des nƓuds, il y aura toujours un Ă©cart lorsque les instances de la version prĂ©cĂ©dente de l'application lisant l'ancien champ fonctionneront simultanĂ©ment avec la nouvelle.
  4. Créez et à la fin du balayage complet de la précédente déployez la version finale, qui n'interagit déjà pas avec l'ancien champ.
  5. Supprimez les anciens champs.

La deuxiĂšme approche nĂ©cessite la crĂ©ation et l'installation de trois versions diffĂ©rentes de l'application, ce qui peut ĂȘtre trĂšs gĂȘnant et encombrant. Au lieu de cela, vous pouvez utiliser le basculement des fonctionnalitĂ©s - pour regrouper la logique des trois versions en une seule, mais changez de mode en fonction du paramĂštre de configuration, qui pourrait idĂ©alement ĂȘtre activĂ© Ă  la volĂ©e. Ainsi, au lieu d'installer chaque version suivante, il suffira de changer la valeur du paramĂštre (et de redĂ©marrer le service si la mise Ă  jour de la configuration Ă  la volĂ©e n'est pas fournie). Une fois l'installation de la version finale terminĂ©e avec succĂšs, tout le code relatif Ă  la migration des donnĂ©es doit ĂȘtre complĂštement supprimĂ© de la branche de travail, mĂȘme s'il "vivra" en production jusqu'Ă  la prochaine mise Ă  jour du systĂšme.

Il est facile de remarquer que garantir un temps d'indisponibilitĂ© nul lors de la mise Ă  jour du systĂšme est une procĂ©dure lourde et fragile, il est donc logique de ne s'en prĂ©occuper que s'il existe une exigence correspondante de la part de l'entreprise. Mais mĂȘme si les exigences de disponibilitĂ© du systĂšme sont assez faibles (par exemple, 99% par an et que la fenĂȘtre de mise Ă  jour du systĂšme prĂ©vue est de 24 heures), la conversion des donnĂ©es requise pour installer la nouvelle version peut encore prendre plus de temps. Par consĂ©quent, vous devez ĂȘtre prĂ©parĂ© Ă  l'avance pour l'utilisation de ces solutions si vous prĂ©voyez de stocker de grandes quantitĂ©s de donnĂ©es.

Une autre approche peut ĂȘtre le rejet intentionnel de modifications incompatibles en amont dans le schĂ©ma de la base de donnĂ©es, mais, malheureusement, dans la pratique, ce n'est pas toujours rĂ©alisable, car souvent le moyen le plus efficace d'amĂ©liorer les performances d'accĂšs aux donnĂ©es est de restructurer le schĂ©ma.

Source: https://habr.com/ru/post/fr423429/


All Articles