如果Slave关闭,Django多个数据库将回退到Master

Jod*_*ddy 16 mysql django multiple-databases python-2.7

我有Django的MySQL数据库后端的主 - 从复制设置.目前我只为Master DB阅读和写作,但我的仪表板非常查询.我正在寻找一个选项,我可以在其中定义如下DATABASES

DATABASES = {
'default_slave': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '3306',
    },
'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '', 
        'PORT': '3306',
    },
}  
Run Code Online (Sandbox Code Playgroud)

对于仪表板,报告和各种其他应用程序,我想要做的是:

尝试连接:default_slave:default_slave如果可以使用,则使用default

也就是说,如果slave已启动,则从slave数据库本身获取报告,如果没有从master数据库获取报告.

Catch是,slave可以是up或down,我希望这可以动态选择哪个数据库用于获取报告,基于可更新性.

这可能吗 ?我可以预先测试连接并向前移动吗?

有了这个,我会在Master中写和sync_db,并且如果slave已启动,它总是从Slave读取.

需要一些解决方案/提示raw queries以及orm queries

路由器的概念看起来不错,但是奴隶的后备不可达,我不知道这种可能性.

UPDATE

如何进行MULTI-DATABASE

DATABASES

DATABASES = {
'default_slave': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '3306',
    },
'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '', 
        'PORT': '3306',
    },
}  
'linux': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '', 
        'PORT': '3306',
    },
}  
'linux_slave': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '', 
        'PORT': '3306',
    },
}  
'mac': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '', 
        'PORT': '3306',
    },
}  
'mac_slave': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '', 
        'PORT': '3306',
    },
}  
'pc': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '', 
        'PORT': '3306',
    },
}  
'pc_slave': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'application',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '', 
        'PORT': '3306',
    },
}  
Run Code Online (Sandbox Code Playgroud)

现在,我有1.静态数据2.动态数据

静态数据必须存储在'default'中,并将其复制到'default_slave'

对于动态数据,查询首先需要判断动态数据的位置:'mac'或'pc'或'linux'

为了实现这一点,我在'静态表'中添加了一个字段:'query_on',其中包含['mac'或'linux'或'pc']

现在,使用查询集,我只是在写 static = Static.objects.get(pk = 1)
query_on = static.query_on dynamic = Dynamic.objects.get(static = static).using(alias=query_on)

这很好用,查询路由到需要执行的数据库,在这里我需要判断:

  1. 如果<'query_on'>_slave:连接已启动:使用:<'query_on'>_slave
  2. 如果<'query_on'>_slave:连接已关闭:使用:<'query_on'>

怎么去那?

申请的进一步细节:

  1. 有一个数据库:默认(配置和分析数据库):用于维护配置数据和报告分析数据
  2. 有20个数据库(原始数据库):例如说:mac,linux,rhel,windows,pc ....(示例名称):用于收集原始数据,这不是分析流程
  3. 每个数据库都有一个或多个从属,命名约定为:default_slave_0,default_slave_1,default_slave_2等等,对于其他数据库也是如此

现在,需要首先每5分钟,30分钟,1小时查询分析数据....并且该查询需要发送到特定数据库,因为并非每个数据库都将携带分析所需的特定数据集.

要做到这一点,我们需要

  1. 从(默认或其任何一个从属(从属部分是问题)获取配置数据)
  2. 一旦我们有了配置,我们就可以轻松地查看"原始"数据的位置
  3. 查询原始数据,收集结果并进行分析 - >将其存储在"默认"数据库中.

现在所有30个(原始)和1个默认数据库都需要"同步",因为我们在所有节点中保持相同的数据abse结构.

现在,由于我们正在查看所有数据库上的CPU峰值,因此使用"slave"数据库查询"原始"数据是有意义的.

因此要求using.我无法想象路由器在这方面会有什么帮助?

kri*_*kus 14

使用路由器,您走在正确的轨道上.我假设您的两个数据库定义相同只是一个错字.

(仅供参考,我将使用更敏感的master-> follower来引用数据库层次结构)

在db_for_read()函数中,您可以检查与关注者的连接.这可能会产生更多的开销,但这是为数据库进行自动故障转移的成本.示例数据库定义是:

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',
    },
}  
Run Code Online (Sandbox Code Playgroud)

你可以通过快速尝试来测试连接/除了这个例子.使用它的路由器可以满足您的需求:

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'
Run Code Online (Sandbox Code Playgroud)

这仍然会像你想要的那样在master中同步.此外,您可以为两者制作逻辑db_for_read()并且db_for_write()更复杂(例如,仅为查询报告的某些模型选择跟随者数据库.

我不知道这test_connection()会导致每次读取的开销,因为这将取决于MySQL服务器和超时.也许更好的架构是使用memcached缓存这些报告,或者只是解决奴隶问题,并首先在设置中更新数据库定义.