第11章 主从复制

MySQL主从复制是高并发场景下的一种集群优化方案。

我们称主服务器为Master,从服务器为Slave,它们是集群中的两种角色。

MySQL主从复制就是将“新数据”从Master主服务器“复制更新”到Slave从服务器上。这样,集群中所有MySQL服务器实例的数据就保持一致了,每一个MySQL服务器实例都可以处理来自客户端的查询请求,从而整体上减轻数据库的压力。

在MySql主从复制的集群方案中,我们一般在Master主服务器上执行“修改”操作,而在Slave从服务器上执行“查询”操作。这就是我们所谓的“读写分离”。在单机的情况下,一般我们做数据库优化都会加索引,但是加了索引对查询有优化,但会影响写入,因为写入数据会更新索引。所以做了主从复制之后,我们可以单独地针对从库(读库)做索引上的优化,而主库(写库)可以减少索引而提高写的效率。

MySQL主从复制的实现方式为:Master主服务器(主库)将“修改”操作写binlog日志,然后Slave从服务器(从库)连接到Master主服务器后(主库)后,通过I/O线程将Master主服务器(主库)的binlog日志写入到本地的relaylog日志,然后从relaylog日志读取binlog日志,最后执行binlog日志中的内容。这样,主库和从库的数据就保持一致了。

备注:主库和从库在初始状态时数据要保持一致。

默认情况下,MySQL主从复制方式是异步的,主库把日志发送给从库后不再做后续确认操作了。这样做的目的显然是考虑了性能问题,但是它不能100%保证从库完成了数据更新。MySQL还有另外两种方式:全同步复制和半同步复制。全同步复制:主库写入 binlog 后,强制同步日志到从库,等所有的从库都执行完成后,才返回结果给客户端,显然这个方式的性能会受到严重影响。半同步复制:从库写入日志成功后返回 ACK(确认)给主库,主库收到至少一个从库的确认就可以认为写操作完成,返回结果给客户端。在实际应用中,你可以根据实际需求选择适合的复制策略。例如,对于数据一致性要求非常高的场景,可以选择全同步复制;对于一般的应用,可以选择异步复制或半同步复制即可。这里需要注意的是,不管是那种复制策略,从库是通过 binlog 文件来同步数据的,这期间会有一定时间的延迟,可能是很短暂的,如果有大量数据修改的话,时间可能更长。

MySQL主从复制常见方案:

第一种:一主多从

此方案一般用来做读写分离,master主库负责修改操作,其他slave从库负责读取操作,这种架构最大问题就是I/O压力集中在Master主库需要同步多台slave从库。

第二种:一主一从多从

这种方案是上面方案的改进版本。它使用一台 slave从库作为中继,分担 Master 主库的I/O压力,Slave中继需要开启 bin-log, 并配置 log-slave-updates 参数,并且Slave 中继可使用 Black-hole 存储引擎,不会把数据存储到磁盘,只记录二进制日志。

第三种:双主互备 (互为主从)

这种方案就是两台master主库,两者相互复制“更新”数据。这种方案可以解决一主多从架构的单点故障,减少主从切换的故障处理时间,增加MySQL群集的高可用性。

第四种:双主互备+多从

这种方案是上面方案的改进版本。双主方案下,很容易因数据访问控制不当导致数据冲突。为提高系统高可用性,双主架构会被扩展成双主多从结构,同样存在主节点发生故障后多个从库选主和恢复复制的问题。

接下来,我们演示“一主一从”方案的实现方式。

两台CentOS主机上都安装好mysql 5.7 版本。

如何在CentOS上安装MySQL请查看:https://blog.csdn.net/richieandndsc/article/details/142746521

主服务器0		192.168.1.100
从服务器1		192.168.1.101

首先,我们在两台Mysql上执行如下脚本,让其初始化数据保持一致。

CREATE DATABASE `test` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

USE `test`;

DROP TABLE IF EXISTS `users`;

CREATE TABLE `users` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(30) NOT NULL DEFAULT '',
  `age` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;

INSERT  INTO `users`(`id`,`name`,`age`) VALUES (1,'张三',20),(2,'李四',22);
select * from users;

+----+--------+-----+
| id | name   | age |
+----+--------+-----+
|  1 | 张三   |  20 |
|  2 | 李四   |  22 |
+----+--------+-----+
2 rows in set (0.00 sec)

备注:两台MySQL实例中的“test”数据库数据是一致的。

第一步:开启master主服务器(IP:192.168.1.100)的二进制日志

vi /etc/my.cnf

[Mysqld]
server-id = 1          			    # 主数据库的id(唯一)
log-bin = master-bin               	# 开启二进制日志
log-bin-index=master-bin.index		# 打开二进制日志文件索引
binlog-ignore-db = sys
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema

:wq

接下来在master主服务器上创建有复制权限的用户(slave从服务器使用)

GRANT REPLICATION SLAVE ON *.* TO 'root'@'192.168.1.101' IDENTIFIED BY '123456';

FLUSH PRIVILEGES;

创建的 root@192.168.1.101 用户对当前数据库的所有库和表进行复制操作

最后重启一下master主服务器

systemctl restart mysqld

重启后可以在 mysql 的安装目录下看到 "log_bin=master-bin" 为开头的日志文件。

接下来,查看master的状态

mysql> show master status;

+----------------------------+---------------+
| File              | Position  |
+----------------------------+---------------+
| master-bin.000001  |   154   |
+----------------------------+---------------+
1 row in set (0.00 sec)

file:是日志文件名称

position:日志所在位置

至此,master主服务器配置完毕了。

第二步:开启slave从服务器(IP:192.168.1.101)的二进制日志

vi /etc/my.cnf

server-id = 2      					        # 从服务器的id(唯一)
relay-log = slave-relay-log 				# 打开从服务器中继日志文件
relay-log-index = slave-relay-log.index  	# 打开从服务器中继日志文件索引

:wq

配置文件修改后必须重启

systemctl restart mysqld

第三步:将slave指向master

mysql> change master to master_host='192.168.1.100', master_user='root', master_password='123456', master_log_file='mysql-bin.000001', master_log_pos=154;

参数master_host就是主服务器的IP地址

参数master_user和master_password就是前面创建的复制权限的用户

参数master_log_file和master_log_pos就是主服务器日志名称和位置(上面刚刚查看了)

这一步说白了,就是让slave从服务器知道从哪里(master主服务器)同步数据。

第四步,在slave服务器上开启主从复制

mysql> start slave;

在slave服务器上执行查看slave运行状态

mysql> show slave status\G;

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

能查看到这两个为yes则成功!!!

错误:Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'

如果发生以上错误,在主服务器上执行:

mysql> flush logs;

Query OK, 0 rows affected (0.01 sec)

刷新一下日志,然后查看状态

mysql> show master status;

+----------------------------+---------------+
| File              | Position  |
+----------------------------+---------------+
| master-bin.000002  |   154   |
+----------------------------+---------------+
1 row in set (0.00 sec)

日志和位置都改变了。

然后在从服务器端执行,重新同步master日志

mysql> stop slave;

mysql> CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000002', MASTER_LOG_POS=154;

mysql> start slave;

mysql> show slave status\G;

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

能查看到这两个为yes则成功!!!

接下来,我们测试主从复制。

我们在master主服务器上执行如下修改命令:

mysql> INSERT INTO `users`(`id`,`name`,`age`) VALUES (3, '王五', 23);

然后我们去slave服务器上查看:

SELECT * FROM users;

+----+--------+-----+
| id | name   | age |
+----+--------+-----+
|  1 | 张三   |  20 |
|  2 | 李四   |  22 |
|  3 | 王五   |  23 |
+----+--------+-----+
3 rows in set (0.00 sec)

数据已经同步过来了!!!

这需要提醒大家的是,假如一个主服务器已经运行了一段时间了,主服务器内存储的有业务数据了,这时候如果要实现主从复制的话,需要我们添加从服务器之后手动同步主服务器业务数据,让其两者数据保持一致,然后才可以实施主从复制策略。

最后需要说明的是,我们的程序在使用MySQL主从复制集群的时候,需要把“更新”操作放到主服务器上执行,而“读取”操作则是在从服务器上执行。这里常用的开源数据库中间件有 Mysql Proxy。MySQL-Proxy是MySQL开源项目,通过自带的lua脚本进行SQL语句判断,可以帮助我们实现读写分离操作。最后还要提一下“Mycat”。 Mycat是一款基于阿里开源产品Cobar而研发的开源数据库分库分表中间件(基于Java语言开发)。Mycat也是数据库中间件,可以实现读写分离、数据分片、多数据源整合等功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值