Lograr la implementación del tiempo de inactividad cero tocó el mismo problema, pero necesito algunos consejos sobre una estrategia que estoy considerando.
Contexto
Una aplicación basada en la web con Apache / PHP para el procesamiento del lado del servidor y MySQL DB / sistema de archivos para la persistencia.
Actualmente estamos construyendo la infraestructura. Todo el hardware de red tendrá redundancia y todos los cables de red principales se utilizarán en pares unidos para tolerancia a fallas. Los servidores se están configurando como pares de alta disponibilidad para la tolerancia a fallos de hardware y se equilibrarán en carga tanto para la tolerancia a fallos de la máquina virtual como para el rendimiento general.
Es mi intención que podamos aplicar actualizaciones a la aplicación sin ningún tiempo de inactividad. Me he esforzado mucho al diseñar la infraestructura para garantizar que pueda proporcionar un tiempo de actividad del 100%; Sería extremadamente decepcionante tener un tiempo de inactividad de 10-15 minutos cada vez que se aplica una actualización. Esto es particularmente significativo ya que pretendemos tener un ciclo de liberación muy rápido (a veces puede alcanzar una o más emisiones por día.
Topología de la red
Este es un resumen de la red:
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: los servidores de base de datos utilizan la replicación maestro-maestro
Estrategia sugerida
Para lograr esto, actualmente estoy pensando en dividir los scripts de actualización del esquema DB en dos partes. La actualización se vería así:
- El servidor web en el nodo A se desconecta; el tráfico continúa siendo procesado por el servidor web en el nodo B.
- Los cambios de esquema de transición se aplican a los servidores de base de datos
- Servidor web Se actualiza una base de código, se borran las memorias caché y se toman otras acciones de actualización.
- El servidor web A se pone en línea y el servidor web B se desconecta.
- La base de código del servidor web B se actualiza, los cachés se borran y se toman otras acciones de actualización.
- El servidor web B se pone en línea.
- Los cambios finales del esquema se aplican a la base de datos
El 'esquema de transición' se diseñaría para establecer una base de datos compatible con versiones cruzadas. Esto utilizaría principalmente vistas de tabla que simulan el esquema de la versión anterior, mientras que la tabla misma se modificaría al nuevo esquema. Esto permite que la versión anterior interactúe con el DB de manera normal. Los nombres de las tablas incluirían números de versión de esquema para garantizar que no haya ninguna confusión sobre a qué tabla escribir.
'Esquema final' eliminaría la compatibilidad con versiones anteriores y ordenaría el esquema.
Pregunta
En resumen, ¿funcionará esto?
más específicamente:
¿Habrá problemas debido al potencial de escrituras concurrentes en el punto específico del cambio de esquema de transición? ¿Hay alguna manera de asegurarse de que el grupo de consultas que modifican la tabla y crean la vista compatible con versiones anteriores se ejecutan consecutivamente? es decir, con cualquier otra consulta retenida en el búfer hasta que se completen los cambios de esquema, que generalmente solo serán milisegundos.
¿Existen métodos más simples que brinden este grado de estabilidad y que también permitan actualizaciones sin tiempo de inactividad? También se prefiere evitar la estrategia de esquema 'evolutivo' ya que no deseo quedar bloqueado en la compatibilidad con esquemas anteriores.
fuente
Tu estrategia es sólida. Solo ofrecería considerar expandir el "Esquema de transición" en un conjunto completo de "tablas de transacciones".
Con las tablas de transacciones, los SELECT (consultas) se realizan contra las tablas normalizadas para garantizar la corrección. Pero todas las INSERTAS, ACTUALIZACIONES y DELETAS de la base de datos siempre se escriben en las tablas de transacciones desnormalizadas.
Luego, un proceso concurrente separado aplica esos cambios (quizás usando procedimientos almacenados) a las tablas normalizadas según las reglas de negocio y los requisitos de esquema establecidos.
La mayoría de las veces, esto sería prácticamente instantáneo. Pero separar las acciones le permite al sistema acomodar la actividad excesiva y los retrasos en la actualización del esquema.
Durante los cambios de esquema en la base de datos (B), las actualizaciones de datos en la base de datos activa (A) irían a sus tablas de transacciones y se aplicarían inmediatamente a sus tablas normalizadas.
Al recuperar la base de datos (B), las transacciones de (A) se aplicarían a ella escribiéndolas en las tablas de transacciones de (B). Una vez que se hace esa parte, (A) podría ser derribado y los cambios de esquema aplicados allí. (B) terminaría de aplicar las transacciones de (A) mientras también manejaba sus transacciones en vivo que se pondrían en cola como lo hizo (A) y los "en vivo" se aplicarían de la misma manera cuando (A) volviera a subir.
Una fila de la tabla de transacciones podría parecerse a ...
Las "tablas" de transacciones podrían ser filas en una base de datos NoSQL separada o incluso archivos secuenciales, según los requisitos de rendimiento. Una ventaja es que la codificación de la aplicación (sitio web en este caso) se vuelve un poco más simple ya que solo escribe en las tablas de transacciones.
La idea sigue los mismos principios que la contabilidad de doble entrada, y por razones similares.
Las tablas de transacciones son análogas a un "diario" de contabilidad. Las tablas totalmente normalizadas son análogas a un "libro de contabilidad" de contabilidad y cada tabla es algo así como una "cuenta" de contabilidad.
En la contabilidad, cada transacción obtiene dos entradas en el diario. Uno para la cuenta contable "debitada" y el otro para la cuenta "acreditada".
En un RDBMS, un "diario" (tabla de transacciones) obtiene una entrada para cada tabla normalizada a ser modificada por esa transacción.
La columna de base de datos en la ilustración de la tabla anterior indica en qué base de datos se originó la transacción, lo que permite que las filas en cola de la otra base de datos se filtren y no se vuelvan a aplicar cuando la segunda base de datos se vuelva a activar.
fuente