Mysql
 sql >> Base de données >  >> RDS >> Mysql

Django Multiple Databases Fallback to Master if Slave is down

Vous êtes sur la bonne voie en utilisant un routeur. Je suppose que le fait que vos deux définitions de base de données soient identiques n'est qu'une faute de frappe.

(Pour votre information, je vais me référer à la hiérarchie de la base de données en utilisant le maître->suiveur le plus sensible )

Dans vos fonctions db_for_read(), vous pouvez vérifier la connectivité à votre suiveur. Cela peut entraîner un peu plus de surcharge, mais c'est le coût du basculement automatique pour une base de données. Un exemple de définition de base de données serait :

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

Vous pouvez tester la connexion avec un essai rapide/sauf comme ceci exemple . Un routeur utilisant ceci qui fait ce dont vous avez besoin ressemblerait à :

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'

Cela sera toujours synchronisé dans master comme vous le souhaitez. En outre, vous pouvez créer la logique pour les deux db_for_read() et db_for_write() plus compliqué (comme choisir la base de données suiveuse uniquement pour certains modèles qui sont interrogés pour vos rapports.

Je ne sais pas quelle surcharge ce test_connection() causera pour chaque lecture, car cela dépendra du serveur MySQL et du délai d'attente. Une meilleure architecture consiste peut-être à mettre ces rapports en cache à l'aide de memcached, ou simplement à résoudre les problèmes liés à l'arrêt de l'esclave et à mettre à jour vos définitions de base de données dans les paramètres en premier.