前言
随着业务的增长,一台数据服务器已经满足不了需求了,负载过重。这个时候就需要减压了,实现负载均衡和读写分离,一主一丛或一主多从。
主服务器只负责写,而从服务器只负责读,从而提高了效率减轻压力。
主从复制方式可以分为:
主从同步:当用户写数据主服务器必须和从服务器同步了才告诉用户写入成功,等待时间比较长。
主从异步:只要用户访问写数据主服务器,立即返回给用户。
主从半同步:当用户访问写数据主服务器写入并同步其中一个从服务器就返回给用户成功。
主从复制的常见架构:一主一从、一主多从、多主多从、双主复制、级联复制(一主+一级从+二级从,一级从复制主库,二级从复制一级从库)
本文以一主三从架构为例,在docker中配置mysql集群,在实际多台服务器中原理基本差不多。
原理和过程
- 主库开启 bin-log,主库会生成一个 Log Dump 线程,用来给从库 I/O 线程传 bin-log;
- 从库生成两个线程,一个 I/O 线程(Slave_IO),一个 SQL 线程(Slave_SQL);
- 从库I/O 线程去请求主库的 bin-log,并将得到的 binlog 日志写到 relay-log (中继日志) 文件中;
- 从库SQL 线程会读取 relay-log 文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致。
拉取镜像
docker pull mysql:5.7
创建容器
执行下面的命令分别创建一台主数据库和3台从数据库,端口分别映射到3306-3309,其中mysql5.7为master库,其余为slave库,如果需要修改目录映射请自行修改参数
docker run -d --restart=always --name mysql5.7 -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:5.7
docker run -d --restart=always --name mysql-slave1 -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 mysql:5.7
docker run -d --restart=always --name mysql-slave2 -e MYSQL_ROOT_PASSWORD=123456 -p 3308:3306 mysql:5.7
docker run -d --restart=always --name mysql-slave3 -e MYSQL_ROOT_PASSWORD=123456 -p 3309:3306 mysql:5.7
执行docker ps
查看容器情况
主库配置
-
开启 bin-log
进入主库,编辑
my.cnf
文件,在[mysqld]
节点下增加下面几行配置开启 bin-log# 服务器唯一id server-id=1 # 设置日志格式,默认值ROW。Statement:只记录 SQL,数据量小,但不能使用mysql函数;ROW:记录被修改的数据,数据量大;MIXED有函数时使用ROW,否则使用Statement binlog_format=MIXED # 二进制日志名,默认binlog log-bin=mysql-bin # 二进制日志保存时间(天) expire_logs_days=7 # 设置不需要复制的数据库 binlog-ignore-db=mysql binlog-ignore-db=infomation_schema binlog-ignore-db=performance_schema binlog-ignore-db=sys
注意注意!!! :上面的配置一定要在
[mysqld]
节点下啊,不然会报错mysql: [ERROR] unknown variable 'server-id=1'
保存后重启主库容器,记得要重启容器啊
-
创建同步用户
同步数据不能使用root用户,我们登陆mysql新建一个
mysql -u root -p
输入密码后创建用户
slave
,密码是123456
CREATE USER 'slave'@'%'; ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%'; FLUSH PRIVILEGES;
-
查看bin-log状态
mysql> show master status; +------------------+----------+--------------+------------------------------------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------------------------------------+-------------------+ | mysql-bin.000001 | 939 | | mysql,infomation_schema,performance_schema,sys | | +------------------+----------+--------------+------------------------------------------------+-------------------+ 1 row in set (0.00 sec)
从库配置
分别进入3个从库,完成下面3个步骤
-
开启relay-log
编辑
my.cnf
文件,增加下面几行配置开启 relay-log# 服务器唯一id,注意每台mysql服务器不要相同 server-id=2 # 中继日志名 relay-log=relay-bin
注意注意!!! :上面的配置一定要在
[mysqld]
节点下啊! -
配置完成保存重启docker从库,然后再重新进入容器进行这一步,一定要重启容器啊
分别执行下面的命令,注意把
注释
和->
去掉mysql> stop slave; mysql> CHANGE MASTER TO MASTER_HOST='192.168.204.128', # 这里的ip填主库的ip,docker环境填宿主机ip地址即可 -> MASTER_PORT=3306, # 这里的ip填主库的端口 -> MASTER_USER='slave', # 用于同步数据的用户,不要用root -> MASTER_PASSWORD='123456', -> MASTER_LOG_FILE='mysql-bin.000001', # 填上一步查看到的主库bin-log文件名 -> MASTER_LOG_POS=154; # 填上一步查看到的主库Position mysql> start slave;
-
查看从库状态
mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.204.128 Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 939 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: .........(后面的信息省略)
注意:上面的
Slave_IO_Running
和Slave_SQL_Running
这两个就是从库的IO
和SQL进程
,状态必须为Yes
才表示连接主库成功,如果是Connecting
,说明链接失败,检查主库ip和mysql账号是不是错了
到这里,主从复制的配置就已经完成了。你在主库的所有操作现在从库应该都能保持同步了,需要注意的是如果你的主库有旧表和数据,那么在主从复制之前,你要把这些表和数据一起复制到从库再开启主从同步,不然SQL
进程就会报错挂掉。