我为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',
},
}
对于仪表板,报告和各种其他应用,我想要做的是:
尝试连接:default_slave:使用default_slave
如果使用default
raw queries
也就是说,如果slave已启动,则从slave数据库本身获取报告,如果没有从master数据库中获取报告。
Catch是,slave可以是up或down,我希望根据可恢复性,可以动态选择哪个数据库用于获取报告。
这可能吗?我可以预先测试连接并向前移动吗?
有了这个,我会在Master中写和sync_db,并且如果slave已经启动,它总是从Slave读取。
需要orm queries
以及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',
},
}
路由器的概念看起来很不错,但奴隶的回退无法到达,我不知道这种可能性。
更新
如何进行MULTI-DATABASE
数据库
static = Static.objects.get(pk = 1)
现在,我有 1.静态数据 2.动态数据
静态数据必须存储在'default'中,并将其复制到'default_slave'
对于动态数据,查询首先需要判断动态数据的位置:'mac'或'pc'或'linux'
为了实现这一点,我在'静态表'中添加了一个字段:'query_on',其中包含['mac'或'linux'或'pc']
现在,使用查询集,我只是在写
query_on = static.query_on
dynamic = Dynamic.objects.get(static = static).using(alias=query_on)
<'query_on'>_slave
这很好用,查询路由到需要执行的数据库,在这里我需要判断:
<'query_on'>_slave
:连接已启动:请使用:<'query_on'>_slave
OR <'query_on'>
:连接已关闭:请使用:using
如何去做?
该应用程序的更多详细信息:
现在需要首先每5分钟,30分钟,1小时查询分析数据....并且该查询需要发送到特定数据库,因为并非每个数据库都将携带分析所需的特定数据集。
要做到这一点,我们需要
现在所有30个(原始)和1个默认数据库都需要“同步”,因为我们在所有节点中保持相同的数据abse结构。
现在,由于我们正在研究所有数据库的CPU峰值,因此使用“slave”数据库查询“原始”数据是有意义的。
因此{{1}}的要求。我无法想象路由器在这里会有什么帮助?答案 0 :(得分:13)
使用路由器,你走在正确的轨道上。我假设您的两个数据库定义相同只是一个错字。
(仅供参考,我将使用the more sensitive 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',
},
}
您可以使用this example之类的快速尝试来测试连接。使用它的路由器可以满足您的需求:
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'
这仍然会像你想要的那样在master中同步。此外,您可以使db_for_read()
和db_for_write()
的逻辑更加复杂(例如,仅为查询报告的某些模型选择跟随者数据库。
我不知道这个test_connection()
会对每次读取产生什么开销,因为这取决于MySQL服务器和超时。也许更好的架构是使用memcached缓存这些报告,或者只是解决奴隶问题,并首先在设置中更新数据库定义。