ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## **什么是MySQL主从同步** **数据是一个应用至关重要的一部分**。从目的出发,主从同步有那么点**备份**的意思,主库(Master)将自己库中的写入同时同步给自己的从库(Slave),当主库发生某些不可预知的状况,导致整个服务器无法使用时,由于从库中也有一份数据,所以数据可以做到快速恢复,**不造成**或者**减少造成**数据的损失。当然,这只是第一个层面,**如果主从库的作用仅限于此**,那么我个人认为没有必要分为两个数据库,只需要定期将数据库内容作为快照发送到另一台服务器,或者每次写入时将写入内容实时发送到另一台服务器不就好了吗,这样不但可以节约资源,也可以起到容灾备份的目的。当然主从同步的作用绝不可能仅限于此,一旦我们配置了主从结构,我们通常不会让从节点仅仅只作为备份数据库,我们应该还会相应地配置上**读写分离**(可以使用MyCat或者其它中间件,可以自己了解一下,关于MyCat我在下一篇博客中会说这个,篇幅可能会有点长,所以就再写一篇吧),在实际环境下,对于数据库的读操作数目远大于对数据库的写操作,所以我们可以让Master只提供写的功能,然后将所有的读操作都移到从库,这就是我们平时常说的**读写分离**,这样可以不但可以减轻Master的压力,还可以做容灾备份,一举两得。 ## **MySQL主从同步的原理** 说完了主从同步的概念,下面来说说主从同步的原理,其实原理也非常简单,没有Redis集群那么多的概念。 实际上当我们在MySQL中配置了主从之后,只要我们对Master节点进行了写操作,这个操作**将会被保存到MySQL的binary-log(bin-log)日志**当中,当slave连接到master的时候,**master机器会为slave开启binlog dump线程**。当master 的 binlog发生变化的时候,Master的dump线程会通知slave,并**将相应的binlog内容发送给Slave**。而Slave节点在主从同步开启的时候,会创建两个线程,一个I/O线程,一个SQL线程,这在我们后面的搭建中可以亲眼看到。 **I/0线程**:该线程链接到master机器,master机器的binlog发送到slave的时候,IO线程会将该日志内容写在本地的**中继日志**(Relay log)中。 **SQL线程**:该线程读取中继日志中的内容,并且根据中继日志中的内容对Slave数据库做相应的操作。 **可能造成的问题**:在写请求相当多的情况下,可能会造成Slave数据和Master数据不一致的情况,这是因为日志传输过程中的短暂延迟、或者写命令较多,系统速度不匹配造成的。 这大致就是MySQL主从同步的原理,真正在其中起到作用的实际上就是这两个日志文件,**binlog**和**中继日志** ![](https://img.kancloud.cn/2c/3b/2c3b1559bed43a54f458f93d767ca50e_435x258.png) ## **手动搭建MySQL主从同步** ### **环境准备** 本次搭建主从同步的环境:CentOS 7 ,MySQL 8.0.18(使用二进制包安装)。 ### **场景介绍** 本次将会搭建MySQL的主从同步,其中一台Master,两台Slave。 ``` Master:IP :192.168.43.201 Port:3306 Slave1:IP:192.168.43.202 Port:3306 Slave2:IP:192.168.43.203 Port:3306 ``` ### **开始搭建** * **修改配置文件** 当我们安装好MySQL之后,在/etc/目录下会有一个my.cnf文件,打开文件,加入如下内容(别忘了修改之前做好备份): ``` #该配置为Master的配置 server-id=201 #Server id 每台MySQL的必须不同 log-bin=/var/lib/mysql/mysql-bin.log #代表开启binlog日志 expire_logs_days=10 #日志过期时间 max_binlog_size=200M #日志最大容量 binlog_ignore_db=mysql #忽略mysql库,表示不同步此库 #该配置为Slave的配置,第二台Slave也是这么配置,不过要修改一下server-id server-id=202 expire_logs_days=10 #日志的缓存时间 max_binlog_size=200M #日志的最大大小 replicate_ignore_db=mysql #忽略同步的数据库 ``` * **新增Slave用户** 打开Master节点的客户端 ,mysql -u root -p 密码 创建用户 create user 'Slave'@'%' identified by '123456'; 给新创建的用户赋权:grant replication slave on '*.*' to 'Slave'@'%'; * **查看Master节点状态** 以上操作都没有问题后,我们在客户端中输入show master status查看master的binlog日志。 ![](https://img.kancloud.cn/95/86/95867a7cd4e6a7b0a78b6aab2dd212ff_496x244.png) * **配置两个Slave节点** 打开两个Slave节点客户端,在我们的另外两个Slave节点中输入如下命令: ``` change master to master_user='Slave',master_password='123456',master_host='192.168.43.201',master_log_file='mysql-bin.000005',master_log_pos=155,get_master_public_key=1; #注意,这里的master_log_file,就是binlog的文件名,输入上图中的mysql-bin.000005,每个人的都可能不一样。 #注意,这里的master_log_pos是binlog偏移量,输入上图中的155,每个人的都可能不一样。 ``` * 配置完成后,输入`start slave;`开启从节点,然后输入`show slave status\G;`查看从节点状态 ![](https://img.kancloud.cn/d4/97/d49775c4b6deac72070ff2f2010007e1_1157x773.png) 可以看到,在两台Slave的状态中,我们能亲眼看到IO线程和SQL线程的运行状态,**这两个线程必须都是yes**,才算配置搭建完成。 * ### **搭建完成** 通过上述步骤,就完成了MySQL主从同步的搭建,相对Redis而言MySQL配置相当简单。下面我们可以进行测试。 先看看三个MySQL的数据库状态:`SHOW DATABASES;` ![](https://img.kancloud.cn/2a/37/2a37aacae54bf65eafc5599070c40f82_1508x207.png) 可以看到现在数据库都是初始默认状态,没有任何额外的库。 在Master节点中创建一个数据库,库名可以自己设置。 `CREATE DATABASE testcluster;` ![](https://img.kancloud.cn/80/54/8054680f683ed037ba6dbc310e192690_1545x227.png) 可以看到,在Slave中也出现了Master中创建的数据库,说明我们的配置没有问题,主从搭建成功。这里就不再创建表了,大家可以自己试试,创建表再往表中插入数据,也是没有任何问题的。 * ### **注意事项** 1. 如果出现IO线程一直在Connecting状态,可以看看是不是三台机器无法相互连接,如果可以相互连接,那么有可能是Slave账号密码写错了,重新关闭Slave然后输入上面的配置命令再打开Slave即可。 2. 如果出现SQL线程为NO状态,那么有可能是从数据库和主数据库的数据不一致造成的,或者事务回滚,如果是后者,先关闭Slave,然后先查看master的binlog和position,然后输入配置命令,再输入`set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;`,再重新`start slave;`即可,如通过是前者,那么就排查一下是不是存在哪张表没有被同步,是否存在主库存在而从库不存在的表,自己同步一下再重新配置一遍即可。