本次我们通过docker搭建环境
- 虚拟机搭建对机器配置有要求,并且安装mysql步骤繁琐
- 一台机器上可以运行多个Docker容器
- Docker容器之间相互独立,有独立ip,互不冲突
- Docker使用步骤简便,启动容器在秒级别
MySQL的主从复制
主从复制(也称 AB 复制)允许将来自一个MySQL数据库服务器(主服务器)的数据复制到一个或多个MySQL数据库服务器(从服务器)。
主从复制的有好处
MySQL中复制的优点包括:
- 横向扩展解决方案 - 在多个从站之间分配负载以提高性能。在此环境中,所有写入和更新都必须在主服务器上进行。但是,读取可以在一个或多个从设备上进行。该模型可以提高写入性能(因为主设备专用于更新),同时显着提高了越来越多的从设备的读取速度。
- 数据安全性 - 因为数据被复制到从站,并且从站可以暂停复制过程,所以可以在从站上运行备份服务而不会破坏相应的主数据。
- 分析 - 可以在主服务器上创建实时数据,而信息分析可以在从服务器上进行,而不会影响主服务器的性能。
- 远程数据分发 - 您可以使用复制为远程站点创建数据的本地副本,而无需永久访问主服务器。
读写分离示意图
主从复制原理
-
主服务器上面的任何修改都会通过自己的 I/O tread(I/O 线程)保存在二进制日志 Binary log 里面。
-
从服务器上面也启动一个 I/O thread,通过配置好的用户名和密码, 连接到主服务器上面请求读取二进制日志,然后把读取到的二进制日志写到本地的一个Realy log(中继日志)里面。
-
从服务器上面同时开启一个 SQL thread 定时检查 Realy log(这个文件也是二进制的),如果发现有更新立即把更新的内容在本机的数据库上面执行一遍。
一主多从
如果一主多从的话,这时主库既要负责写又要负责为几个从库提供二进制日志。此时可以稍做调整,将二进制日志只给某一从,这一从再开启二进制日志并将自己的二进制日志再发给其它从。或者是干脆这个从不记录只负责将二进制日志转发给其它从,这样架构起来性能可能要好得多,而且数据之间的延时应该也稍微要好一些。
MySQL主从复制搭建步骤
由于我们依托于docker容器,所以要求大家预先有docker的知识铺垫。
服务器规划
服务器 | 软件 | 用途 |
---|---|---|
192.168.0.108 | docker | 启动MySQL容器master |
192.168.0.109 | docker | 启动MySQL容器slave |
192.168.0.1010 | docker | 启动MySQL容器slave |
主服务器搭建
步骤1:镜像拉取
首先在192.168.0.108拉取docker镜像,我们这里使用5.7版本的mysql
[root@bogon ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mysql 5.7 e1e1680ac726 7 months ago 373 MB
创建目录mysql-conf
[root@bogon mysql-conf]# pwd
/usr/local/mysql-conf
在当前目录中创建配置文件my.cnf,次文件要映射到mysql的docker容器中的配置文件,文件中加入[mysqld]
[root@bogon mysql-conf]# vi my.cnf
[root@bogon mysql-conf]# more my.cnf
[mysqld]
步骤2:主机MySQL容器创建
创建主机容器
Master对外映射的端口是5566,Slave对外映射的端口是5577。因为docker容器是相互独立的,每个容器有其独立的ip,所以不同容器使用相同的端口并不会冲突。
docker run -p 5566:3306 --name master-mysql -v/usr/local/mysql-conf/:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
查看容器运行情况
[root@bogon mysql-conf]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1f93892498df mysql:5.7 "docker-entrypoint..." 4 minutes ago Up 4 minutes 33060/tcp, 0.0.0.0:5566->3306/tcp master-mysql
步骤3:修改外部映射文件my.cnf
[root@bogon mysql-conf]# more my.cnf
[mysqld]
skip-name-resolve
server-id=1
log-bin=mysql-bin
binlog-do-db=tx_db
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
进入容器内可以查看到数据卷映射后的结果
[root@bogon mysql-conf]# docker exec -it 1f93892498df /bin/bash
root@1f93892498df:/etc/mysql/conf.d# more my.cnf
[mysqld]
skip-name-resolve
server-id=1
log-bin=mysql-bin
binlog-do-db=tx_db
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
重启容器
docker restart 1f93892498df
步骤四:赋予从机权限
登录mysql,授予192.168.0.109, 192.168.0.110 slave从机复制权限
mysql> grant replication slave,replication client on *.* to slave@'192.168.0.109' identified by "123456";
Query OK, 0 rows affected
mysql> flush privileges;
Query OK, 0 rows affected
mysql> grant replication slave,replication client on *.* to slave@'192.168.0.110' identified by "123456";
Query OK, 0 rows affected
mysql> flush privileges;
Query OK, 0 rows affected
查看主机状态
mysql> show master status;
+------------------+----------+--------------+--------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000001 | 154 | tx_db | mysql,information_schema | |
+------------------+----------+--------------+--------------------------+-------------------+
1 row in set
从服务器搭建
步骤1:启动两台从机
从节点配置文件创建
在192.168.0.109和192.168.0.110新建目录/usr/local/mysql-conf/
创建 my.cnf
192.168.0.109机器
[root@file mysql-conf]# more my.cnf
[mysqld]
skip-name-resolve
server-id= 2
log-bin=mysql-bin
replicate-do-db=tx_db
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
192.168.0.110机器
[root@file mysql-conf]# more my.cnf
[mysqld]
skip-name-resolve
server-id= 3
log-bin=mysql-bin
replicate-do-db=tx_db
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
启动slave1(109)
[root@file mysql-conf]# docker run -p 5577:3306 --name slave-mysql1 -v /usr/local/mysql-conf/:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
启动slave1(110)
[root@localhost mysql-conf]# docker run -p 5588:3306 --name slave-mysql1 -v /usr/local/mysql-conf/:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
此时我们可以看到三台MySQL服务器都已经启动,并且连接
步骤2:每一台从机创建用户赋权
mysql> CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
Query OK, 0 rows affected
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
Query OK, 0 rows affected
mysql> flush privileges;
Query OK, 0 rows affected
mysql> stop slave;
Query OK, 0 rows affected
mysql>
步骤3 在每一台从机创建从机
分别在109和110机器执行。
mysql> change master to master_host='192.168.0.108', master_user='slave', master_password='123456', master_port=5566, master_log_file='mysql-bin.000002', master_log_pos= 154, master_connect_retry=30;
Query OK, 0 rows affected
说明:
master_host :Master的地址,指的是容器的独立ip
master_port:Master的端口号,指的是容器的端口号
master_user:用于数据同步的用户
master_password:用于同步的用户的密码
master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
master_log_pos:从哪个 Position 开始读,即上文中提到的 Position 字段的值
master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒
检查两台从机状态:
我们发现从机已经创建,但是内部线程还未启动
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.0.108
Master_User: slave
Master_Port: 5566
Connect_Retry: 30
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 154
Relay_Log_File: d55404be5426-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB: tx_db
正常情况下,SlaveIORunning 和 SlaveSQLRunning 都是No,因为我们还没有开启主从复制过程。使用start slave开启主从复制过程,然后再次查询主从同步状态show slave status \G;。
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.0.108
Master_User: slave
Master_Port: 5566
Connect_Retry: 30
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 154
Relay_Log_File: d55404be5426-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: tx_db
在主库中创建tx_db数据库,我们发现从库可以同步出来
更详细的Spring源码解析请关注:java架构师免费课程
每晚20:00直播分享高级java架构技术
扫描加入QQ交流群264572737