Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Django Multiple Databases Fallback para Master se Slave estiver inativo


Você está no caminho certo com o uso de um roteador. Estou assumindo que o fato de que suas duas definições de banco de dados são idênticas é apenas um erro de digitação.

(Para sua informação, vou me referir à hierarquia do banco de dados usando o mestre->seguidor mais sensível )

Em suas funções db_for_read(), você pode verificar a conectividade com seu seguidor. Isso pode gerar um pouco mais de sobrecarga, mas esse é o custo de ter um failover automático para um banco de dados. Um exemplo de definição de banco de dados seria:
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',
    },
}  

Você pode testar a conexão com um rápido try/except como this exemplo . Um roteador usando isso que faz o que você precisa se pareceria com:
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'

Isso ainda será sincronizado no master como você deseja. Além disso, você pode fazer a lógica para db_for_read() e db_for_write() mais complicado (como escolher o db seguidor apenas para determinados modelos que são consultados para seus relatórios.

Eu não sei que sobrecarga esta test_connection() causará para cada leitura, pois isso dependerá do servidor MySQL e do tempo limite. Talvez uma arquitetura melhor seja armazenar em cache esses relatórios usando o memcached ou apenas resolver os problemas com o escravo sempre caindo e atualizar suas definições de banco de dados nas configurações primeiro.