定义及路由机制

定义

在settings里面的DATABASES是一个字典,用于定义需要的数据库,如下,一共定义了两个数据库。

DATABASES = {

'default': {

'NAME': 'app_data',

'ENGINE': 'django.db.backends.postgresql_psycopg2',

'USER': 'postgres_user',

'PASSWORD': 's3krit'

},

'user1': {

'NAME': 'user1_data',

'ENGINE': 'django.db.backends.mysql',

'USER': 'mysql_user',

'PASSWORD': 'priv4te'

}

'user2': {

'NAME': 'user2_data',

'ENGINE': 'django.db.backends.mysql',

'USER': 'mysql_user',

'PASSWORD': 'priv4te'

}

}

那么什么时候调用default什么时候调用users数据库呢,这就需要下面的路由。

路由注册

class User1Router(object):

"""

A router to control all database operations on models in the

auth application.

"""

def db_for_read(self, model, **hints):

"""

Attempts to read auth models go to auth_db.

"""

if model._meta.app_label == 'auth':

return 'user1'

return None

def db_for_write(self, model, **hints):

"""

Attempts to write auth models go to auth_db.

"""

if model._meta.app_label == 'auth':

return 'user1'

return None

def allow_relation(self, obj1, obj2, **hints):

"""

Allow relations if a model in the auth app is involved.

"""

if obj1._meta.app_label == 'auth' or \

obj2._meta.app_label == 'auth':

return True

return None

def allow_syncdb(self, db, model):

"""

Make sure the auth app only appears in the 'auth_db'

database.

"""

if db == 'auth_db':

return model._meta.app_label == 'auth'

elif model._meta.app_label == 'user1':

return False

return None

class User2Router(object):

"""

A router to control all database operations on models in the

auth application.

"""

def db_for_read(self, model, **hints):

"""

Attempts to read auth models go to auth_db.

"""

if model._meta.app_label == 'auth2':

return 'user2'

return None

def db_for_write(self, model, **hints):

"""

Attempts to write auth models go to auth_db.

"""

if model._meta.app_label == 'auth2':

return 'user2'

return None

def allow_relation(self, obj1, obj2, **hints):

"""

Allow relations if a model in the auth app is involved.

"""

if obj1._meta.app_label == 'auth' or \

obj2._meta.app_label == 'auth':

return True

return None

def allow_syncdb(self, db, model):

"""

Make sure the auth app only appears in the 'auth_db'

database.

"""

if db == 'auth_db':

return model._meta.app_label == 'auth2'

elif model._meta.app_label == 'user2':

return False

return None

User1Router的路由逻辑是,如果model所属的app是auth的话,就使用user1数据库,否则就使用其他的;User2Router的逻辑类似。

如何注册路由

光定义路由程序无法调用到,还需要注册到django中,在settings中定义

DATABASE_ROUTERS = ['path.to.User1Router' , 'path.to.User2Router']

path.to:是User1Router的完整python包路径,所以,User1Router不一定要在settings中实现,可以在任何地方。

路由机制

那么django是如何选择其中一个路由的呢?

1. django按照注册的顺序轮询DATABASE_ROUTERS,所以首先验证User1Router是否返回了非空字符串,如果是,则使用User1Router;如果不是则接着验证后面的Router;

2. 同样验证User2Router,如果User2Router返回了非空字符串,则使用User2Router;如果不是则使用default数据库;

3. 所以可以看出,路由注册的顺序是会影响最后的结果的,注册在前面的路由会优先被使用;

自动路由和手动路由

上面定义的Router是自动路由,意思是django会自动轮询所注册的路由器,某个model会保存在哪个数据库,是django通过注册的Router自动获得的,在编码中你不需要指定;

手动路由,则是你可以在编码中指定某个model要保存到哪个数据库。

而且手动路由也有性能方面的优点,如果定义了很多个数据库,每次保存或者读取model都要把轮询一遍路由列表,显然效率有些低,如果程序逻辑清楚的知道当前的代码应该连接哪个数据库,显示指定的方式显然效率更高。

手动路由

查询

使用using函数,参数就是要查询的数据库

User.objects.using('user1').all()

保存或者更新

使用save的using参数,值就是要使用的数据库

>>> my_object.save(using='user1')

删除

使用delete的using参数

>>> user_obj.delete(using='user1')

分库技术

下面紧紧介绍分库的思路。

垂直分库

即一个app对应一个数据库,上面自动路由的例子就是一个垂直分库的例子,auth1使用user1数据库,auth2使用user2数据库。当然也可以使用手动路由。

水平分库

水平分库建议使用手动路由,因为每个model的分库机制可能都不一样,自动路由实现起来有些麻烦会造成性能不高,而手动路由,每个model根据自己的规则来获得不同的数据库。

补充知识:Django实现数据库读写分离、一主多从、分库

读写分离

在工程中,通常需要实现mysql读写分离。在Django中需要支持读写分离的话,只需要很简单的几步就可以了。

首先,配置读库和写库。

在django项目的settings.py中,配置读库和写库。

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.mysql',

'NAME': 'WIPS',

'USER': 'mysql',

'PASSWORD': '360tianxun#^)Sec',

'HOST': '',

'PORT': '',

},

'slave': {

'ENGINE': 'django.db.backends.mysql',

'NAME': 'TEST',

'USER': 'mysql',

'PASSWORD': '360tianxun#^)Sec',

'HOST': '',

'PORT': '',

},

}

接下来,需要创建数据库的路由分发类。

可以在appname/utils下创建一个db_router.py文件,在文件中定义db_router类。类中实现读库写库的选择。

class DBRouter(object):

def db_for_read(self, model, **hints):

return "slave"

def db_for_write(self, model, **hints):

return "default"

def allow_relation(self, obj1, obj2, **hints):

return True

最后,在settings.py中添加路由配置。

DATABASE_ROUTERS = ['appname.utils.db_router.DBRouter' ]

重新启动Django就完成了。

这里需要注意的是,Django只完成了读写分离,但mysql主库、从库的同步操作并不归django负责,依然需要mysql实现。

一主多从

一主多从的方案在实际应用中是更常见的配置。在上面配置的基础上,只需要修改几个地方,就可以实现一主多从了。

首先,修改settings.py,增加全部从库的设置。

其次,修改db_router类中db_for_read(),下面是随机选取读库的例子。也可以根据实际的需要,选取不同的调度算法。

class DBRouter(object):

def db_for_read(self, model, **hints):

import random

return random.choice(['slave', 'slave2', 'slave3'])

分库

当需要不同的app使用不同的库时,可以利用model中的app_label来实现db的路由。

class DBRouter(object):

def db_for_read(self, model, **hints):

if model._meta.app_label == 'app01':

import random

return random.choice(['app01_slave1', 'app01_slave2', 'app01_slave3'])

if model._meta.app_label == 'app02':

return "app02_slave"

按照上面的操作就很容易实现mysql的读写分离、一主多从和分库了。但这个方法只建议用在小项目上。

以上这篇django 多数据库及分库实现方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持python博客。

django写mysql轮询_django 多数据库及分库实现方式相关推荐

  1. 【纸上得来终觉浅】RoundRobinRule源码分析后,自己手写了轮询算法

    前言 今天自己查看了RoundRobinRule的源码,通过读源码走断点,大概自己知道了源码中,参数调用,下面我是查阅相关源代码,反正看过源代码以后总感觉纸上得来终觉浅,绝知此事要躬行,然后编写了轮询 ...

  2. django 操作MySQL 中文乱码_Django 连接mysql数据库中文乱码

    版本:CentOS6.8 python3.6.4 django1.8.2 数据库pymysql 我使用的终端是CentOS终端,CentOS桌面版安装的pycham,windows使用Navicat连 ...

  3. django和mysql如何建模_Django中的多个数据库和多个模型

    小编典典 我完全同意@alecxe使用数据库路由器.我目前正在使用一个管理界面来管理多个数据库.请注意,所有数据库的身份验证都存储在默认数据库中,因此当你执行syncdb(不带参数)时. 通用数据库路 ...

  4. Django使用mysql连接池_Django db使用MySQL连接池

    Django db使用MySQL连接池 Sep 25 2016 Django db模块本身不支持MySQL连接池,只有一个配置CONN_MAX_AGE连接最大存活时间,如果WSGI服务器使用了线程池技 ...

  5. django给mysql配主从_django中的mysql主从读写分离:一、配置mysql主从分离

    一.配置mysql主从同步的步骤: (1) 在主服务器上,必须开启二进制日志机制和配置一个独立的ID (2) 在每一个从服务器上,配置一个唯一的ID,创建一个用来专门复制主服务器数据的账号 (3) 在 ...

  6. django和mysql如何建模_Django如何设计数据模型

    app中的models建立好了后,并不会自动地在数据库中生成相应的数据表,需要你手动创建. 进入Pycharm的terminal终端,执行下面的命令: python manage.py makemig ...

  7. django与mysql实现增删_django与mysql实现简单的增删查改

    模型定义 from django.db import models class Grades(models.Model): g_name = models.CharField(max_length=2 ...

  8. c语言写程序轮询是什么意思,单片机轮询按键程序

    #include #define uchar unsigned char //按键端口定义 sbit io_key_1 = P2^0 ; sbit io_key_2 = P2^1 ; sbit io_ ...

  9. mysql 的几种缓存,数据库缓存几种方式 -解道Jdon

    数据库缓存的几种方式 引入缓存可以提高性能,但是数据会存在两份,一份在数据库中,一份在缓存中,如果更新其中任何一份会引起数据的不一致,数据的完整性被破坏了,因此,同步数据库和缓存的这两份数据就非常重要 ...

最新文章

  1. 牛津大佬|计算机科学方向一对一科研项目
  2. 阿里云ET工业大脑发布AI视觉产品“见远”:电池片、车辆、路面都能被“诊断”...
  3. check的用法java,Java ValueRange checkValidValue()用法及代码示例
  4. python简单代码表白-python浪漫表白源码
  5. mac mysql创建本地数据库_【mac】配置本地数据库
  6. linux开机启动roscore,树莓派ubuntuMate系统中开机自启动ROS的launch文件
  7. android pdf生成 路径,android – 如何从指向PDF文档的URI获取文件路径?
  8. Linux下磁盘阵列raid
  9. c++除法保留小数_BigDecimal 加减乘除、保留小位数
  10. python 爬虫代码实例
  11. 中文实体关系抽取实践
  12. 长春理工大学第六届CTF网络攻防大赛题解(文末有题目下载链接)
  13. 电容的字母型规格型号标号材料容差总结
  14. 会员权益营销如何助力会员指数增长
  15. 【前端】JS的BOM和DOM,事件,表单验证案例
  16. 弱爆了的鹊桥专用查询接口:taobao.tbk.dg.item.coupon.get( 好券清单API【导购】)接口
  17. 3D数学——法线变换
  18. 抗锯齿和走样(笔记)
  19. 【OpenGL】平面法向量、顶点法向量的计算方法
  20. 华为——OSPF单区域实验配置,实验抓包分析,五种报文分析,六种LSA介绍,以及如何建立邻接关系的七种状态

热门文章

  1. java中使用es的dsl_基于DSL的基于图论的Java程序中输入图数据的方法
  2. 使用JUnit 5在Mockito中方便地进行模拟–官方方式
  3. weblogic运行项目_在WebLogic 12c上运行RichFaces
  4. 使用Hibernate和Spring设置分布式Infinispan缓存
  5. 2016年成功的Java开发人员简介
  6. 在Java 8中使用Rhino
  7. 使用WSO2 ESB进行邮件内容过滤
  8. 使用JDK 8流在包装对象的集合和包装对象的集合之间转换
  9. 借助Java 8和lambdas,可以一起使用AssertJ和Awaitility
  10. Java中的硬件事务性内存,或者为什么同步将再次变得很棒