转:https://blog.csdn.net/Ayhan_huang/article/details/78784486

转:http://www.cnblogs.com/dreamer-fish/p/5469141.html

配置数据库

创建models并执行数据库迁移

读写分离

  手动读写分离

  自动读写分离

  配置Router

  一主多从方案

  分库分表

实测

简述

对网站的数据库作读写分离(Read/Write Splitting)可以提高性能,在Django中对此提供了支持,下面我们来简单看一下。注意,还需要运维人员作数据库的读写分离和数据同步。

配置数据库

我们知道在Django项目的settings中,可以配置数据库,除了默认的数据库,我在下面又加了一个db2。因为是演示,我这里用的是默认的SQLite,如果希望用MySQL,看这里 。

DATABASES = {
    'default': {
         'ENGINE': 'django.db.backends.sqlite3',
         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
     },
     'db2': {
         'ENGINE': 'django.db.backends.sqlite3',
         'NAME': os.path.join(BASE_DIR, 'db2.sqlite3'),

创建models并执行数据库迁移

这里我简单创建一张产品表

from django.db import models


 class Products(models.Model):
     """产品表"""
     prod_name = models.CharField(max_length=30)
     prod_price = models.DecimalField(max_digits=6, decimal_places=2)


创建完成后,执行数据库迁移操作:

python manage.py makemigrations  # 在migrations文件夹下生成记录,迁移前检查
python manage.py migrate  # 创建表
# 
python manage.py migrate --database default
python manage.py migrate --database db2  # 根据settings里的名称逐个迁移


在migrations文件夹下生成记录,并在迁移前检查是否有问题,默认值检查defualt数据库,但是可以在后面的数据库路由类(Router)中通过allow_migrate()方法来指定是否检查其它的数据库。

其实第二步迁移默认有参数python manage.py migrate --database default ,在默认数据库上创建表。因此完成以上迁移后,执行python manage.py --database db2,再迁移一次,就可以在db2上创建相同的表。这样在项目根目录下,就有了两个表结构一样的数据库,分别是db.sqlite3和db2.sqlite3。

读写分离

手动读写分离

在使用数据库时,通过.using(db_name)来手动指定要使用的数据库

from django.shortcuts import HttpResponse
from . import models


 def write(request):
     models.Products.objects.using('default').create(prod_name='熊猫公仔', prod_price=12.99)
     return HttpResponse('写入成功')


def read(request):
     obj = models.Products.objects.filter(id=1).using('db2').first()
     return HttpResponse(obj.prod_name)

自动读写分离

通过配置数据库路由,来自动实现,这样就不需要每次读写都手动指定数据库了。数据库路由中提供了四个方法。这里这里主要用其中的两个:def db_for_read()决定读操作的数据库,def db_for_write()决定写操作的数据库。

定义Router类

新建myrouter.py脚本,定义Router类:

class Router:
     def db_for_read(self, model, **hints):
         return 'db2'

    def db_for_write(self, model, **hints):
         return 'default'

配置Router

settings.py中指定DATABASE_ROUTERS

    DATABASE_ROUTERS = ['myrouter.Router',] 


可以指定多个数据库路由,比如对于读操作,Django将会循环所有路由中的db_for_read()方法,直到其中一个有返回值,然后使用这个数据库进行当前操作。

一主多从方案

网站的读的性能通常更重要,因此,可以多配置几个数据库,并在读取时,随机选取,比如:

class Router:
     def db_for_read(self, model, **hints):
         """
         读取时随机选择一个数据库
        """
         import random
         return random.choice(['db2', 'db3', 'db4'])

    def db_for_write(self, model, **hints):
         """
         写入时选择主库
        """
         return 'default'

分库分表

在大型web项目中,常常会创建多个app来处理不同的业务,如果希望实现app之间的数据库分离,比如app01走数据库db1,app02走数据库

class Router:
     def db_for_read(self, model, **hints):
         if model._meta.app_label == 'app01':
             return 'db1'
         if model._meta.app_label == 'app02':
             return 'db2'

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'app01':
             return 'db1'
        if model._meta.app_label == 'app02':
             return 'db2'

例子

别人的例子

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testly',
        'USER': 'root',
        'PASSWORD': '123456789',
        'HOST':'192.168.1.1',
        'PORT':'3306',
    },
    'hvdb':{   #配置第二个数据库节点名称
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testdjango', #第二个数据库的名称
        'USER': 'root',
        'PASSWORD': '123456789',
        'HOST':'192.168.1.1',
        'PORT':'3306',   
    }
}


DATABASE_ROUTERS = ['tt.db_router.app02Router'] #tt为当前项目名称,db_router为上一步编写的db_router.py文件,app02Router为Router
#DATABASE_ROUTERS = ['tt.db_router.app02Router','tt.db_router.app01Router'] #如果定义了多个Router,在此就需要分别指定。注意:这个是有顺序的(先匹配上的规则,就先生效)
settings.py

相关文章:

  • 2022-12-23
  • 2022-01-07
  • 2022-12-23
  • 2022-02-21
  • 2021-12-18
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-01-07
  • 2022-12-23
  • 2022-02-28
  • 2021-11-09
  • 2021-08-10
  • 2022-12-23
相关资源
相似解决方案