Mysql
 sql >> Database >  >> RDS >> Mysql

Django Database multipli fallback su Master se Slave è inattivo

Sei sulla buona strada con l'utilizzo di un router. Presumo che il fatto che le tue due definizioni db siano identiche sia solo un errore di battitura.

(Cordiali saluti, farò riferimento alla gerarchia del database utilizzando il maestro più sensibile->seguace )

Nelle tue funzioni db_for_read(), puoi verificare la connettività al tuo follower. Questo potrebbe comportare un po' più di sovraccarico, ma questo è il costo del failover automatico per un database. Una definizione di database di esempio potrebbe essere:

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',
    },
}  

Puoi testare la connessione con un rapido tentativo/tranne come questo esempio . Un router che utilizza questo che fa ciò di cui hai bisogno sarebbe simile a:

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'

Questo sincronizzerà comunque il master come desideri. Inoltre, potresti creare la logica per entrambi db_for_read() e db_for_write() più complicato (come scegliere il db follower solo per alcuni modelli che vengono interrogati per i tuoi rapporti.

Non so quale sia il sovraccarico di questo test_connection() causerà per ogni lettura, poiché dipenderà dal server MySQL e dal timeout. Forse un'architettura migliore consiste nel memorizzare nella cache questi report utilizzando memcached o semplicemente risolvere i problemi con lo slave che si interrompe e aggiornare prima le definizioni del database nelle impostazioni.