Mysql主从搭建与Django实现读写分离

Mysql主从搭建与Django实现读写分离

主从同步原理

在这里插入图片描述

  1. master 会将变动记录写道二进制日志里面
  2. master 通过一个I/O线程将二进制日志发送到slave中
  3. slave 有一个I/O线程把master发送到的二进制写入relay日志里面
  4. slave 有一个SQL线程,按照relay日志处理slave的数据

总结: 简单点说 不论是mysql主从还是redis主从,其核心原理在于通过日志同步执行的更改命令,一般主库用来写,从库用来读。

主从同步实现

这里采用docker在同一台机器上模拟两台mysql服务器

  1. 创建两个文件夹 mysql 和 mysql2 两者里面风别有 data和conf.d文件夹和 my.cnf 配置文件
# 主库的配置文件 my.cnf
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000
server-id=100    # 局域网内唯一
log-bin=mysql-bin  # 开启binlog日志(二进制日志功能,可以随便取(关键))

# 从库配置文件
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000
server-id=101
# 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave-bin  
# relay_log配置中继日志
relay_log=edu-mysql-relay-bin 
  1. docker启动命令
# 使用docker 启动mysql容器,映射目录 data,my.cnf   master
docker run  -di -v /py20/mysql/data/:/var/lib/mysql/ -v /py20/mysql/conf.d:/etc/mysql/conf.d -v /py20/mysql/my.cnf:/etc/mysql/my.cnf -p 3306:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
                    
# 使用docker 启动mysql容器,映射目录 data,my.cnf   
docker run  -di -v /py20/mysql2/data/:/var/lib/mysql -v /py20/mysql2/conf.d:/etc/mysql/conf.d -v /py20/mysql2/my.cnf:/etc/mysql/my.cnf -p 3307:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7          
  1. 创建用户,搭建主从
# 从库要复制 bin-log日志---》使用用户复制---》在主库创建用户并授予权限--》root用户不行
	-这个用户连接到主库上,复制数据,需要所有权限
1. 进入容器中连接mysql
	docker exec -it 76c9727e709b /bin/bash
2. ##创建test用户
  create user 'test'@'%' identified by '123';
  ##授权用户
  grant all privileges on *.* to 'test'@'%' ;
  ###刷新权限
  flush privileges;
  #查看主服务器状态
  show master status;      
    
3. # 连接从库
    # 从库中连接主库账户
    change master to master_host='139.5.60.54',master_port=3307,master_user='test',master_password='123',master_log_file='mysql-bin.000003',master_log_pos=0;
    #启用从库
    start slave;
    #查看从库状态(如下图)
    show slave status\G;   # 双yes就成功了

在这里插入图片描述

在这里插入图片描述

Django实现读写分离

django读写分离 基于mysql主从同步的基础实现

1. 数据库配置
    DATABASES = {
	'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': ip,
        'USER': user,
        'PASSWORD': password,
        'NAME': database-master,
        'PORT': '3306',
        'CHARSET': 'utf-8',
    },
    'slave': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': ip,
        'USER': user,
        'PASSWORD': password,
        'NAME': database-slave,
        'PORT': '3307',
        'CHARSET': 'utf-8',
    },
    }
2. 使用
	1. 手动指定 .objects.using('slave')  默认是default
    2. 写一个路由自动读写分离
        class DatabaseAppsRouter(object):
        def db_for_read(self, model, **hints):
           # 从models中取出表名---》通过这个可以更细粒度的控制哪个表哪个库查
            '''可以通过model进行更细粒度的控制进行分库分表'''
            return 'slave'

        def db_for_write(self, model, **hints):
            return 'default'
        
        # 需要在配置文件中配置
		DATABASE_ROUTERS = ['django_databases.db_routers.DatabaseAppsRouter']

进阶

  • 多数据库读写分离
class DBRouter(object):
    def db_for_read(self, model, **hints):
        """
        Reads go to a randomly-chosen replica.
        """
        if model._meta.app_label == 'monitor':
            return 'monitor'
        elif model._meta.app_label == 'analysis':
            return 'analysis'
        else:
            return random.choice(['slave'])
        # return random.choice(['slave'])

    def db_for_write(self, model, **hints):
        """
        Writes always go to primary.
        """
        if model._meta.app_label == 'analysis':
            return 'analysis'
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the primary/replica pool.
        """
        db_list = ('default', 'slave')
        if obj1._state.db in db_list and obj2._state.db in db_list:
            return True
        return None

    def allow_migrate(self, db, app_label, model=None, **hints):
        return True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

go&Python

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值