欢迎访问我的个人网站,网站正在创建期间,主要供自己学习交流使用!

Django MySQL数据库主从配置



  主从同步使得数据可以从一个数据库服务器复制到其他服务器上,在复制数据时,一个服务器充当主服务器(master),其余的服务器充当从服务器(slave)。因为复制是异步进行的,所以从服务器不需要一直连接着主服务器,从服务器甚至可以通过拨号断断续续地连接主服务器。通过配置文件,可以指定复制所有的数据库,某个数据库,甚至是某个数据库上的某个表。主从配置通过增加从服务器来提高数据库的性能,在主服务器上执行写入和更新,在从服务器上向外提供读功能,可以动态地调整从服务器的数量,从而调整整个数据库的性能。

提高数据安全,因为数据已复制到从服务器,从服务器可以终止复制进程,所以,可以在从服务器上备份而不破坏主服务器相应数据。

在主服务器上生成实时数据,而在从服务器上分析这些数据,从而提高主服务器的性能。

主从配置的原理

  主从配置是基于二进制日志来实现的,主服务器在执行增删改查时会将相关指令都记录在二进制日志文件中,然后从服务器通过读取和执行该文件来保持和主服务器一致。

apt-get install docker docker-io

mysql --help

mysql  Ver 8.0.21-0ubuntu0.20.04.4 for Linux on x86_64 ((Ubuntu))

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

sudo docker image pull mysql:8.0.21

运行mysql docker镜像,需要在宿主机中建立文件目录用于mysql容器保存数据和读取配置文件:

cd

mkdir mysql_slave

cd mysql_slave

mkdir data

cp -a /etc/mysql/mysql.conf.d ./    #将位于/etcmysql配置文件拷贝过来

sudo netstat -an|grep 3306

tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN

docker运行的mysql作为slave来运行,开启前需要修改配置文件。编辑 ~/mysql_slave/mysql.conf.d/mysqld.cnf 文件,修改:

port  =  3309  #区别开主服务器的3306

general_log  = 0

server-id  = 2 #主服务器id设为1,从服务器取2,有多个从服务器可依此编号

创建docker容器,要指定ubuntudocker里面映射的路径(-v后面就是指定的映射路径),详细命令如下(--network=host表示无端口映射,docker设置的端口和主机一致)

sudo docker run --name mysql-slave -e MYSQL_ROOT_PASSWORD=Yisl04_Wll -d --network=host -v /home/yisl04/mysql_slave/data:/var/lib/mysql -v /home/yisl04/mysql_slave/mysql.conf.d:/etc/mysql/mysql.conf.d  mysql:8.0.21

为了避免mysqlx33060端口冲突,需要端口映射(33070-host,33060-docker)

sudo docker run -d --name mysql-slave -e MYSQL_ROOT_PASSWORD=Yisl04_Wll -p 33070:33060 -p 3309:3309 -v /home/yisl04/mysql_slave/data:/var/lib/mysql -v /home/yisl04/mysql_slave/mysql.conf.d:/etc/mysql/mysql.conf.d   mysql:8.0.21 --default-authentication-plugin=mysql_native_password

sudo docker ps -a

CONTAINER ID IMAGE  COMMAND   CREATED   STATUS    PORTS     NAMES

40e42dadc5b1 mysql:8.0.21 "docker-entrypoint.s…" 23 minutes ago Up 22 minutes       3306/tcp, 0.0.0.0:3309->3309/tcp, 0.0.0.0:33090->33060/tcp   mysql-slave

docker logs 40e42dadc5b1(注意此为容器id,勿跟镜像)

docker rm 40e42dadc5b1

sudo systemctl restart docker

接下来备份初始主服务器的内容到从服务器,后续的备份则通过二进制日志来传输:

sudo mysqldump –uroot -p –h127.0.0.1 –P3306 --all-databases --lock-all-tables > ~/master_db.sql

sudo docker cp ~/master_db.sql 40e42dadc5b1:/home/

#上面的命令是将主服务器的所有数据库备份,并拷贝到containerhome目录下,下面的命令则是恢复到docker里面的mysql上。

sudo docker exec -it mysql-slave bash

#mysql  -uroot –p –hlocalhost –P3309 < /home/master_db.sql

 

接下来配置主服务器的配置:

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf  #进入配置文件

server-id = 1  #[mysqld]下方输入这两条指令

log_bin =  /var/log/mysql/mysql-bin.log

然后重启mysql

sudo /etc/init.d/mysql restart

接着创建slave使用的账号密码:

mysql –uroot –p   #输入密码,进入mysql

GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' identified by 'yisl430723';

FLUSH PRIVILEGES; #执行权限

#*.*表示所有表,slave表示账号,yisl430723表示密码

如果是mysql8.0之后需要先创建用户,之后才能授权:

//delete from mysql.user where user='slave' and host='localhost';

create user 'slave'@'%' IDENTIFIED BY 'yisl430723';

alter user 'slave'@'%' identified with mysql_native_password by 'yisl430723';

GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%';

FLUSH PRIVILEGES; #执行权限

mysql> show grants for 'slave'@'%';

 

mysql> show master status;

File为使用的日志文件名字,Position为使用的文件位置,这两个参数须记下,配置从服务器时会用到。

   进入docker中的mysql配置从服务器的slave

sudo docker exec -it mysql-slave bash

# mysql -uroot -p -hlocalhost -P3309

mysql> change master to master_host='127.0.0.1', master_user='slave', master_password='yisl430723', master_log_file='mysql-bin.000002', master_log_pos=1230;

mysql> start slave;

mysql> show slave status \G

  1. 在配置文件中增加slave数据库的配置

DATABASES = {

    'default': {

        ...

    },

    'slave': {

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

        'HOST': '127.0.0.1',

        'PORT': 3309,

        'USER': 'root',

        'PASSWORD': 'Yisl04_Wll',

        'NAME': 'rockwool'

    }

}

  1. 创建数据库操作的路由分发类(用于创建数据库的路由分发)

class MasterSlaveDBRouter(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

  1. 配置读写分离路由

DATABASE_ROUTERS = ['utils.db_router.MasterSlaveDBRouter']


湘公网安备43012102001039    湘ICP备14007447号-1    邮箱:35744243#qq.com