随着业务量的增加,数据也会越来越多。如果,以前数据只部署在一台机器上,有可能会造成 MySQL 的性能瓶颈,关于 MySQL 的优化及相关 SQL 语句的编写,接下来会在 MySQL 的一个章节中讲到,本小节,是部署分布式的第一小节,简单的 MySQL 一主多从模式。

        MySQL 主从复制,带来的好处有以下几点(希望高人能补充):

  1. 数据分布:可以根据地区,网络等分散部署服务器;
  2. 负载均衡:及在读写分离的基础上,将负载均衡的分散到每台 MySQL 服务器上;
  3. 备份:这个很好理解,既然做了读写分离,多台数据库上的数据肯定是一致的;
  4. 高可用性和容错性:利用相关扩展,实现主备切换。

        一主多从(读写分离)的实现原理:

  1. MySQL 支持单向、异步数据复制;
  2. MySQL 复制基于主服务器在二进制日志中跟踪所有对数据库的更改(新增、更新、删除等);
  3. 从服务器从主服务器接收主服务器已经记录到其二进制日志的保存的内容。

        MySQL 内部实现步骤:

  1. 主服务器将改变记录到二进制(binary log)中;
  2. 从服务器将主服务器的 binary log events 拷贝到它的中继日志(relay log);
  3. 从服务器重做中继日志中的事件,将改变作用到从服务器本身的数据。

        可以在虚拟机中,克隆出几台相同环境的服务器,需要确保每台机器的 IP 和初始化网卡的 MAC 地址,网络连接可以采用桥接模式。

    环境的准备

在这里,我们假设101是主服务器,现在想增加一台102的从服务器。因为,101上已经有一部分数据了,而102则是一台全新的服务器。

主服务器 MySQL :

从服务器 MySQL :本小节的内容,就是把 101 的数据同步到 102 上,然后实现简单的一对多的读写分离模式,虽然这里只有一台从服务器,原理上其它的从服务器配置都是一样。

    将主服务器数据备份到从服务器
mysql> flush tables with read lock;

将主服务器( Master )设为对所有用户只读状态,如果尝试去写操作,会报如下错误,可能会根据不同的用户报不同的错误,关于 MySQL 的锁等相关内容,将会在 MySQL 栏目中详细介绍。

    利用 mysqldump 备份主库数据
#> mysqldump -uroot -p --databases shop > /home/wwwroot/bak/shopdump.sql

如果,没有对应的目录,可以利用 mkdir -p 创建下。

    将 shopdump.sql 备份文件上传到从服务器
#> cd /home/wwwroot/bak
#> scp shopdump.sql root@192.168.0.102:/home/wwwroot/bak/


    从服务器还原备份数据
/**
* 两种还原方式
* 1、命令行下还原
*/
#> mysql -uroot -p < /home/wwwroot/bak/shopdump.sql
// 2、mysql 终端还原
mysql> source /home/wwwroot/bak/shopdump.sql;

现在,主( Master )从( slave )数据一样的了,开始配置读写分离相关配置。

    配置 Master 的 my.cnf

log-bin:binlog日志文件;binlog_format:日志文件格式,有默认的statement,基于sql语句的复制,row基于行的复制;mixed:混合方式;server-id:服务器id,要保证唯一;expire_logs_days:binlog日志过期清理时间。

    重启 MySQL 服务
#> systemctl restart mysql
    查看 Master 状态和重置

reset master 将删除所有的二进制日志,创建一个.000001的空日志。并不会影响 slave 服务器上的工作状态,所以盲目的执行这个命令会导致 slave 找不到 master 的binlog,造成同步失败。我们这里不受影响。

    修改 Slave 的 my.cnf 文件

默认是开启binlog日志,这里关闭它,把中继日志relay_log开启。重启 Slave 服务器。

    停止 Slave 并重置


    Master 授权 slave 账户 备份的权限
mysql> grant replication slave on *.* to slave@192.168.0.102 identified by '123456';

账户 slave 可以通过192.168.0.102,密码 123456,来备份 Master 上的所有库和所有表,仅仅是备份权限。

    Slave 监听指定的 Master
    mysql> change master to
         > master_host='192.168.0.101',
> master_port=3306,
> master_user='slave',
> master_password='123456',
> master_log_file='mysql-bin.000001',
> master_log_pos=331;

_host,_port,_user,_password分别是:Master 所在的主机、端口、分配 slave 的用户和密码。_log_file 和 _log_pos 根据 Master 主机当前状态来填写,Master 上执行: show master status; 由于每次操作,log_pos 会不同,取最新的即可。

    Slave 开启 start slave,并查看 slave 状态 show slave status\G

会看到报这样的一个错误,因为我们的虚拟机环境都是复制过来的,MySQL5.7 引用了 UUID 机制,解决方法:先停止 slave 机器(systemctl stop mysql),进入到存放数据的文件夹( /usr/local/mysql/var)下,会有一个 auto.cnf 文件,删除它,重启 mysql 服务就会自动生成。然后重试一次。

出现两个 yes ,说明主从复制配置完成,通过异步线程 IO 去读取 Master binlog 日志。

    释放 Master 上的全局读锁
mysql> unlock table;
    测试主从复制
// 101 ( Master)
mysql> insert into `user` (`name`, `email`) values ('boris', 'boris@163.co,');
// 102 ( Slave )
mysql> select * from `user`;

这时,在 Slave 服务器上,就有对应的数据插入了。如果,是一开始就部署读写分离,主从复制的话,上面的那些数据备份与还原的步骤是不需要的。下一小节,将介绍下,主备切换(容灾)模式。

    总结一下
  1. 主从数据库的数据一致
  2. Master 需要创建一个授权账号,允许复制
  3. 记录 Master 的状态:File 和 Position
  4. Slave 指定监听的 

由于能力有限,不足或有不解之处,希望在下方评论区与我讨论,共同提高 。