Zero tempi di fermo macchina - Schema Db transitorio


14

La realizzazione di Zero Downtime Deployment ha toccato lo stesso problema, ma ho bisogno di alcuni consigli su una strategia che sto prendendo in considerazione.

Contesto

Un'applicazione web con Apache / PHP per l'elaborazione lato server e MySQL DB / filesystem per la persistenza.

Attualmente stiamo costruendo l'infrastruttura. Tutto l'hardware di rete avrà ridondanza e tutti i cavi di rete principali verranno utilizzati in coppie legate per la tolleranza agli errori. I server vengono configurati come coppie ad alta disponibilità per la tolleranza agli errori hardware e saranno bilanciati in base al carico sia per la tolleranza agli errori della macchina virtuale che per le prestazioni generali.

È mia intenzione che siamo in grado di applicare gli aggiornamenti all'applicazione senza tempi di inattività. Ho preso molta cura nel progettare l'infrastruttura per assicurarmi di poter fornire il 100% di tempo di attività; sarebbe estremamente deludente avere 10-15 minuti di inattività ogni volta che è stato applicato un aggiornamento. Ciò è particolarmente significativo poiché intendiamo avere un ciclo di rilascio molto rapido (a volte può raggiungere una o più versioni al giorno.

Topologia di rete

Questo è un riepilogo della rete:

                      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

Nota: i server DB utilizzano la replica master-master

Strategia suggerita

Per raggiungere questo obiettivo, sto attualmente pensando di suddividere gli script di aggiornamento dello schema DB in due parti. L'aggiornamento sarebbe simile al seguente:

  1. Il server Web sul nodo A è disattivato; il traffico continua ad essere elaborato dal web server sul nodo B.
  2. Le modifiche allo schema di transizione vengono applicate ai server DB
  3. Server Web Una base di codice viene aggiornata, le cache vengono cancellate e vengono intraprese eventuali altre azioni di aggiornamento.
  4. Il server Web A viene portato in linea e il server Web B viene portato offline.
  5. La base di codice B del server Web viene aggiornata, le cache vengono cancellate e vengono intraprese eventuali altre azioni di aggiornamento.
  6. Il web server B viene portato online.
  7. Le modifiche dello schema finale vengono applicate al DB

Lo "schema transitorio" verrebbe progettato per stabilire un DB compatibile tra versioni. Ciò farebbe principalmente uso delle viste della tabella che simulano lo schema della vecchia versione mentre la tabella stessa verrebbe modificata al nuovo schema. Ciò consente alla versione precedente di interagire normalmente con il DB. I nomi delle tabelle includeranno i numeri di versione dello schema per garantire che non vi sia alcuna confusione su quale tabella scrivere.

"Schema finale" rimuove la compatibilità con le versioni precedenti e riordina lo schema.

Domanda

In breve, funzionerà?

più specificamente:

  1. Ci saranno problemi dovuti al potenziale di scritture simultanee nel punto specifico della modifica dello schema di transizione? C'è un modo per assicurarsi che il gruppo di query che modifica la tabella e crea la vista compatibile con le versioni precedenti sia eseguito consecutivamente? vale a dire con qualsiasi altra query trattenuta nel buffer fino al completamento delle modifiche dello schema, che generalmente saranno solo millisecondi.

  2. Esistono metodi più semplici che offrono questo grado di stabilità, consentendo al contempo aggiornamenti senza tempi di inattività? Si preferisce anche evitare la strategia dello schema "evolutivo" poiché non desidero essere bloccato nella compatibilità dello schema all'indietro.

Risposte:


4

Sembra che ciò che stai davvero cercando non sia la disponibilità elevata, ma la disponibilità continua .

Fondamentalmente il tuo piano funzionerà, ma sembra che tu abbia notato che il principale difetto nella tua configurazione è che le modifiche dello schema del database in una versione potrebbero comportare downtime o il mancato funzionamento del nodo ancora disponibile. L'approccio della disponibilità continua risolve questo problema creando essenzialmente un numero di ambienti di produzione.

Production One

Questo ambiente è la tua attuale versione live del software utilizzato dagli utenti. Ha i propri server Web, server applicazioni e server database e tablespace. Funziona indipendentemente da qualsiasi altro ambiente. Il bilanciamento del carico che possiede l'endpoint di risoluzione del dominio per questi servizi sta attualmente puntando a questi server Web.

Produzione due

Questo è fondamentalmente un ambiente di gestione temporanea del rilascio identico a Production One. È possibile eseguire gli aggiornamenti di rilascio qui ed eseguire i test di integrità prima dell'evento live. Ciò consente anche di eseguire in modo sicuro le modifiche al database in questo ambiente. Il bilanciamento del carico non punta attualmente a questo ambiente.

Produzione DR

Questo è un altro duplicato in un data center separato che si trova in una diversa regione del mondo. Ciò consente di eseguire il failover in caso di evento catastrofico eseguendo uno switch DNS su Load Balancer.

Andare in diretta

Questo evento sta essenzialmente aggiornando il record DNS per passare alla produzione due dalla produzione 1 o viceversa. Questo richiede un po 'di tempo per propagarsi nei server DNS del mondo in modo da lasciare entrambi gli ambienti in esecuzione per un po'. Alcuni utenti potrebbero lavorare in sessioni esistenti sulla versione precedente del software. La maggior parte degli utenti stabilirà nuove sessioni sulla versione aggiornata del software.

Migrazione dei dati

L'unico inconveniente qui è che non tutti i dati durante quella finestra sono disponibili per tutti gli utenti in quel momento. Esistono chiaramente dati utente importanti nel database della versione precedente che ora devono essere migrati in modo sicuro nel nuovo schema del database. Ciò può essere realizzato con uno script di esportazione e migrazione dei dati ben collaudato o un processo batch o un processo ETL simile.

Conclusione

Dopo aver completato completamente il tuo evento di rilascio, Production Two è ora il tuo principale e inizi a lavorare sull'installazione della versione successiva su Production One per il ciclo di distribuzione successivo.

svantaggi

Questa è una configurazione di ambiente complessa e richiede una grande quantità di risorse di sistema, spesso da due a tre volte le risorse di sistema per funzionare correttamente. Operare in questo modo può essere costoso, soprattutto se si dispone di sistemi di uso pesante molto grandi.


Quindi, se ho capito bene, tu suggerisci che invece di una modifica dello schema DB "transizionale" che viene applicata mentre il Db è ancora in uso, Db-A viene mantenuto online con il vecchio schema mentre Db-B viene aggiornato al nuovo schema. Quando l'aggiornamento è pronto per il rilascio, i server Web vengono cambiati e i dati scritti in Db A durante la preparazione dell'aggiornamento vengono migrati in Db B (presumibilmente applicando tutte le modifiche dopo un determinato timestamp).
Marvin,

@PeterScott Hai capito. Tieni a mente che non vuoi eseguire lo script fino a quando non sei sicuro che tutte le sessioni attive siano finite nel vecchio sistema ed è stato un tempo abbastanza lungo che tutte le cache DNS sono state aggiornate al nuovo CNAME o indirizzo IP.
maple_shaft

1
Dovrei essere ok su entrambi questi punti; le sessioni vengono mantenute nel Db anziché nell'archiviazione del server per evitare che le sessioni siano legate a specifiche macchine virtuali e al momento intendo provare a utilizzare un bilanciamento del carico non basato su DNS. Non avrò ridondanza a livello di data center, ma ciò può attendere circa un anno dopo l'avvio dell'applicazione.
Marvin,

2

La tua strategia è solida. Vorrei solo considerare di espandere il "Schema di transizione" in un set completo di "tabelle delle transazioni".

Con le tabelle delle transazioni, i SELECT (query) vengono eseguiti rispetto alle tabelle normalizzate al fine di garantire la correttezza. Ma tutti gli INSERT, i UPDATE e i DELETE del database vengono sempre scritti nelle tabelle delle transazioni denormalizzate.

Quindi un processo separato e simultaneo applica tali modifiche (magari utilizzando Stored procedure) alle tabelle normalizzate secondo le regole aziendali e i requisiti dello schema stabiliti.

Il più delle volte, questo sarebbe praticamente istantaneo. Ma la separazione delle azioni consente al sistema di gestire eccessivi ritardi di aggiornamento dello schema e delle attività.

Durante le modifiche dello schema sul database (B), gli aggiornamenti dei dati sul database attivo (A) andavano nelle sue tabelle delle transazioni e venivano immediatamente applicati alle sue tabelle normalizzate.

Al ripristino del database (B), le transazioni da (A) verrebbero applicate ad esso scrivendole nelle tabelle delle transazioni (B). Una volta terminata quella parte, (A) potrebbe essere rimosso e le modifiche dello schema applicate lì. (B) avrebbe finito di applicare le transazioni da (A) gestendo anche le sue transazioni live che si sarebbero messe in coda proprio come faceva (A) e le "transazioni live" sarebbero state applicate allo stesso modo quando (A) sarebbe tornato.

Una riga della tabella delle transazioni potrebbe essere simile 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=...

Le "tabelle" di transazione potrebbero effettivamente essere righe in un database NoSQL separato o persino file sequenziali, a seconda dei requisiti di prestazione. Un vantaggio è che la codifica dell'applicazione (sito Web in questo caso) diventa un po 'più semplice poiché scrive solo nelle tabelle delle transazioni.

L'idea segue gli stessi principi della contabilità in partita doppia e per ragioni analoghe.

Le tabelle delle transazioni sono analoghe a un "journal" contabile. Le tabelle completamente normalizzate sono analoghe a un "libro mastro" di contabilità con ogni tabella che è in qualche modo come un "account" di contabilità.

Nella contabilità, ogni transazione ottiene due voci nel giornale di registrazione. Uno per il conto contabile "addebitato" e l'altro per l'account "accreditato".

In un RDBMS, un "journal" (tabella delle transazioni) ottiene una voce per ogni tabella normalizzata che deve essere modificata da quella transazione.

La colonna DB nell'illustrazione della tabella sopra indica su quale database ha avuto origine la transazione, consentendo così di filtrare e non riapplicare le righe in coda dell'altro database quando viene ripristinato il secondo database.


1
Mi piace il confronto con la contabilità. Quindi, se ho capito, le tabelle delle transazioni mi permettono di mettere un piccolo ritardo nella scrittura dei dati su una particolare tabella normalizzata in modo da poter applicare tutte le modifiche dello schema senza il rischio di interruzione a metà strada attraverso le modifiche? Quindi, con lo schema della tabella aggiornato, posso riprendere il processo che applica le transazioni denormalizzate alle tabelle normalizzate (questo processo è in grado di mappare le query dei dati del vecchio schema sul nuovo schema)?
Marvin,

1
Sì. Modifichereste le procedure memorizzate di mapping (o qualsiasi altra cosa) per adattarsi a dati vecchi e nuovi. Le nuove colonne NOT-NULL potrebbero essere riempite da vecchi dati con un codice che significa "richiedi questo sull'aggiornamento dell'utente". Le colonne da dividere (cioè FULLNAME in FIRST e LAST) avrebbero bisogno di un algoritmo. Consiglio di aggiungere 1 o più colonne "simili a commenti" alle tabelle per i nuovi requisiti di biz che emergono. In caso contrario, garantisco agli utenti di appropriarsi di altre colonne a tale scopo e la correzione dei dati sarà quasi impossibile.
DocSalvager,

Come impedire che le query SELECT strutturate per il vecchio schema vengano applicate al nuovo schema? Potrei usare creare una vista tabella e rinominare la tabella dello schema (con un numero di versione dello schema) ma ciò sarebbe comunque problematico mentre le modifiche dello schema vengono applicate poiché si applicano direttamente alla tabella normalizzata.
Marvin,

1
Quando aggiungi una tabella, una colonna o qualsiasi altra cosa a un RDBMS, in realtà stai semplicemente aggiungendo delle righe a un set di tabelle interne che possono essere scritte solo dal motore RDBMS. I DBA gestiscono il database eseguendo una query tramite VIEW. Dal momento che Oracle, IBM, MS, ecc. Sono gli esperti e dicono che questo è il modo migliore, sembra che dovremmo seguire il loro esempio. Crea una serie di VISUALIZZAZIONI per ogni versione dell'applicazione. Puoi modellarli dopo le tabelle (di solito abbastanza denormalizzate) che gli sviluppatori vogliono che tu crei in modo da poter normalizzare correttamente per prevenire dati corrotti.
DocSalvager,

Grazie. Dovrò pensarci. sto creando un livello ORM nell'applicazione che rimuove completamente tutta la logica di persistenza dello stato dal dominio principale; essendo più basato sulla programmazione lato server tendo a risolvere i problemi più da quel lato che dal lato amministrazione DB. Usando la mia strategia attuale, il Db sarebbe piuttosto piatto con l'ORM che gestiva attivamente le tabelle non elaborate. L'aggiunta di viste di tabella e, possibilmente, di un registro delle transazioni aggiunge una maggiore complessità all'ORM, ma consente anche di supportare più versioni dello schema senza la suddivisione dei dati.
Marvin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.