sql >> Base de Datos >  >> RDS >> Mysql

Django Bases de datos múltiples Respaldo al maestro si el esclavo está inactivo

Está en el camino correcto con el uso de un enrutador. Supongo que el hecho de que sus dos definiciones de db sean idénticas es solo un error tipográfico.

(Para su información, me referiré a la jerarquía de la base de datos usando el más sensible maestro->seguidor )

En sus funciones db_for_read(), puede verificar la conectividad con su seguidor. Esto podría generar un poco más de gastos generales, pero ese es el costo de tener una conmutación por error automática para una base de datos. Una definición de base de datos de ejemplo sería:

DATABASES = {
'follower': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'follower',
        'USER': 'root',
        'HOST': '54.34.65.24',
        'PORT': '3306',
    },
'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'HOST': '54.34.65.23',
        'PORT': '3306',
    },
}  

Puede probar la conexión con un intento rápido/excepto como este ejemplo . Un enrutador que use esto y haga lo que necesita se vería así:

from django.conf import settings
import socket


def test_connection_to_db(database_name):
    try:
        db_definition = getattr(settings, 'DATABASES')[database_name]
        s = socket.create_connection((db_definition['HOST'], db_definition['PORT']), 5)
        s.close()
        return True
    except (AttributeError, socket.timeout) as e:
        return False


class FailoverRouter(object):
    """A router that defaults reads to the follower but provides a failover back to the default"""

    def db_for_read(self, model, **hints):
        if test_connection_to_db('follower'):
            return 'follower'
        return 'default'

    def db_for_write(self, model, **hints):
        "Point all writes to the default db"
        return 'default'

    def allow_syncdb(self, db, model):
        "Make sure only the default db allows syncdb"
        return db == 'default'

Esto aún se sincronizará en el maestro como quieras. Además, podría hacer la lógica para ambos db_for_read() y db_for_write() más complicado (como elegir la base de datos de seguidores solo para ciertos modelos que se consultan para sus informes.

No sé qué sobrecarga esta test_connection() causará por cada lectura, ya que eso dependerá del servidor MySQL y el tiempo de espera. Tal vez una mejor arquitectura es almacenar en caché estos informes usando Memcached, o simplemente resolver los problemas con el esclavo y actualizar primero las definiciones de su base de datos en la configuración.