目录

基础环境介绍

搭建主从集群

1、理论基础

2.同步的原理

搭建主从集群

配置master主服务器

配置slave从服务

主从集群测试

集群搭建扩展:

​2、读写分离配置

​3、其他集群方式


基础环境介绍

两台服务器,均安装CentOS7。

​ 1、127.0.0.1 作为mysql主节点部署

​ 2、127.0.0.1 作为mysql从节点部署

mysql版本:mysql-8.0.20

为了便于使用,两个mysql服务需要打开远程登录权限,开启方式需要在本机登录mysql,执行以下语句。

#开启远程登录use mysql;update user set host='%' where user='root';flush privileges;

搭建主从集群

1、理论基础

主从架构有什么用?通过搭建MySQL主从集群,可以缓解MySQL的数据存储以及访问的压力。

1、数据安全

​ 给主服务增加一个数据备份。基于这个目的,可以搭建主从架构,或者也可以基于主从架构搭建互主的架构。

2、读写分离

​ 对于大部分的JAVA业务系统来说,都是读多写少的,读请求远远高于写请求。这时,当主服务的访问压力过大时,可以将数据读请求转为由从服务来分担,主服务只负责数据写入的请求,这样大大缓解数据库的访问压力。

​ 要理解,MySQL的主从架构只是实现读写分离的一个基础。实现读写分离还是需要一些中间件来支持,比如ShardingSphere。

3、故障转移-高可用

​ 当MySQL主服务宕机后,可以由一台从服务切换成为主服务,继续提供数据读写功能。

​ 对于高可用架构,主从数据的同步也只是实现故障转移的一个前提条件,要实现MySQL主从切换,还需要依靠一些其他的中间件来实现。比如MMM、MHA、MGR。

​ 在一般项目中,如果数据库的访问压力没有那么大,那读写分离不一定是必须要做的,但是,主从架构和高可用架构则是必须要搭建的。

2.同步的原理

MySQL服务的主从架构一般都是通过binlog日志文件来进行的。即在主服务上打开binlog记录每一步的数据库操作,然后从服务上会有一个IO线程,负责跟主服务建立一个TCP连接,请求主服务将binlog传输过来。这时,主库上会有一个IO dump线程,负责通过这个TCP连接把Binlog日志传输给从库的IO线程。接着从服务的IO线程会把读取到的binlog日志数据写入自己的relay日志文件中。然后从服务上另外一个SQL线程会读取relay日志里的内容,进行操作重演,达到还原数据的目的。我们通常对MySQL做的读写分离配置就必须基于主从架构来搭建。

MySQL的binlog不光可以用于主从同步,还可以用于缓存数据同步等场景。

例如Canal,可以模拟一个slave节点,向MySQL发起binlog同步,然后将数据落地到Redis、Kafka等其他组件,实现数据实时流转。

搭建主从集群

配置master主服务器

首先,配置主节点的mysql配置文件: /etc/my.cnf 这一步需要对master进行配置,主要是需要打开binlog日志,以及指定severId。我们打开MySQL主服务的my.cnf文件,在文件中一行server-id以及一个关闭域名解析的配置。然后重启服务。

[mysqld]server-id=47#开启binloglog_bin=master-binlog_bin-index=master-bin.indexskip-name-resolve# 设置连接端口port=3306# 设置mysql的安装目录basedir=/usr/local/mysql# 设置mysql数据库的数据的存放目录datadir=/usr/local/mysql/mysql-files# 允许最大连接数max_connections=200# 允许连接失败的次数。max_connect_errors=10# 服务端使用的字符集默认为UTF8character-set-server=utf8# 创建新表时将使用的默认存储引擎default-storage-engine=INNODB# 默认使用“mysql_native_password”插件认证#mysql_native_passworddefault_authentication_plugin=mysql_native_password

配置说明:主要需要修改的是以下几个属性:

server-id:服务节点的唯一标识。需要给集群中的每个服务分配一个单独的ID。

log_bin:打开Binlog日志记录,并指定文件名。

log_bin-index:Binlog日志文件

​ 重启MySQL服务,service mysqld restart

​ 然后,我们需要给root用户分配一个replication slave的权限。

#登录主数据库mysql -u root -pGRANT REPLICATION SLAVE ON *.* TO 'root'@'%';flush privileges;#查看主节点同步状态:show master status;

在实际生产环境中,通常不会直接使用root用户,而会创建一个拥有全部权限的用户来负责主从同步。

这个指令结果中的File和Position记录的是当前日志的binlog文件以及文件中的索引。

​ 而后面的Binlog_Do_DB和Binlog_Ignore_DB这两个字段是表示需要记录binlog文件的库以及不需要记录binlog文件的库。目前我们没有进行配置,就表示是针对全库记录日志。这两个字段如何进行配置,会在后面进行介绍。

开启binlog后,数据库中的所有操作都会被记录到datadir当中,以一组轮询文件的方式循环记录。而指令查到的File和Position就是当前日志的文件和位置。而在后面配置从服务时,就需要通过这个File和Position通知从服务从哪个地方开始记录binLog。

配置slave从服务

​ 下一步,我们来配置从服务mysqls。 我们打开mysqls的配置文件my.cnf,修改配置文件:

[mysqld]#主库和从库需要不一致server-id=48#打开MySQL中继日志relay-log-index=slave-relay-bin.indexrelay-log=slave-relay-bin#打开从服务二进制日志log-bin=mysql-bin#使得更新的数据写进二进制日志中log-slave-updates=1# 设置3306端口port=3306# 设置mysql的安装目录basedir=/usr/local/mysql# 设置mysql数据库的数据的存放目录datadir=/usr/local/mysql/mysql-files# 允许最大连接数max_connections=200# 允许连接失败的次数。max_connect_errors=10# 服务端使用的字符集默认为UTF8character-set-server=utf8# 创建新表时将使用的默认存储引擎default-storage-engine=INNODB# 默认使用“mysql_native_password”插件认证#mysql_native_passworddefault_authentication_plugin=mysql_native_password

配置说明:主要需要关注的几个属性:

server-id:服务节点的唯一标识

relay-log:打开从服务的relay-log日志。

log-bin:打开从服务的bin-log日志记录。

然后我们启动mysqls的服务,并设置他的主节点同步状态。

#登录从服务mysql -u root -p;#设置同步主节点:CHANGE MASTER TOMASTER_HOST='127.0.0.1',MASTER_PORT=3306,MASTER_USER='root',MASTER_PASSWORD='root',MASTER_LOG_FILE='master-bin.000004',MASTER_LOG_POS=156GET_MASTER_PUBLIC_KEY=1;#开启slavestart slave;#查看主从同步状态show slave status;或者用 show slave status \G; 这样查看比较简洁

注意,CHANGE MASTER指令中需要指定的MASTER_LOG_FILE和MASTER_LOG_POS必须与主服务中查到的保持一致。

并且后续如果要检查主从架构是否成功,也可以通过检查主服务与从服务之间的File和Position这两个属性是否一致来确定。

我们重点关注其中红色方框的两个属性,与主节点保持一致,就表示这个主从同步搭建是成功的。

从这个指令的结果能够看到,有很多Replicate_开头的属性,这些属性指定了两个服务之间要同步哪些数据库、哪些表的配置。只是在我们这个示例中全都没有进行配置,就标识是全库进行同步。后面我们会补充如何配置需要同步的库和表。

主从集群测试

​ 测试时,我们先用showdatabases,查看下两个MySQL服务中的数据库情况

然后我们在主服务器上创建一个数据库

mysql> create database syncdemo;Query OK, 1 row affected (0.00 sec)

然后我们再用show databases,来看下这个syncdemo的数据库是不是已经同步到了从服务。

​ 接下来我们继续在syncdemo这个数据库中创建一个表,并插入一条数据。

mysql> use syncdemo;Database changedmysql> create table demoTable(id int not null);Query OK, 0 rows affected (0.02 sec)mysql> insert into demoTable value(1);Query OK, 1 row affected (0.01 sec)

​ 然后我们也同样到主服务与从服务上都来查一下这个demoTable是否同步到了从服务。

从上面的实验过程看到,我们在主服务中进行的数据操作,就都已经同步到了从服务上。这样,我们一个主从集群就搭建完成了。

另外,这个主从架构是有可能失败的,如果在slave从服务上查看slave状态,发现Slave_SQL_Running=no,就表示主从同步失败了。这有可能是因为在从数据库上进行了写操作,与同步过来的SQL操作冲突了,也有可能是slave从服务重启后有事务回滚了。

如果是因为slave从服务事务回滚的原因,可以按照以下方式重启主从同步:

mysql> stop slave ;mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;mysql> start slave ;

而另一种解决方式就是重新记录主节点的binlog文件消息

mysql> stop slave ;mysql> change master to .....mysql> start slave ;

但是这种方式要注意binlog的文件和位置,如果修改后和之前的同步接不上,那就会丢失部分数据。所以不太常用。

集群搭建扩展:

1、全库同步与部分同步

首先在Master端:在my.cnf中,可以通过以下这些属性指定需要针对哪些库或者哪些表记录binlog

#需要同步的二进制数据库名binlog-do-db=masterdemo#只保留7天的二进制日志,以防磁盘被日志占满(可选)expire-logs-days= 7#不备份的数据库binlog-ignore-db=information_schemabinlog-ignore-db=performation_schemabinlog-ignore-db=sys

然后在Slave端:在my.cnf中,需要配置备份库与主服务的库的对应关系。

#如果salve库名称与master库名相同,使用本配置replicate-do-db = masterdemo #如果master库名[mastdemo]与salve库名[mastdemo01]不同,使用以下配置[需要做映射]replicate-rewrite-db = masterdemo -> masterdemo01#如果不是要全部同步[默认全部同步],则指定需要同步的表replicate-wild-do-table=masterdemo01.t_dictreplicate-wild-do-table=masterdemo01.t_num

2、读写分离配置

​ 我们要注意,目前我们的这个MySQL主从集群是单向的,也就是只能从主服务同步到从服务,而从服务的数据表更是无法同步到主服务的。

​ 所以,在这种架构下,为了保证数据一致,通常会需要保证数据只在主服务上写,而从服务只进行数据读取。这个功能,就是大名鼎鼎的读写分离。但是这里要注意下,mysql主从本身是无法提供读写分离的服务的,需要由业务自己来实现。这也是我们后面要学的ShardingSphere的一个重要功能。

到这里可以看到,在MySQL主从架构中,是需要严格限制从服务的数据写入的,一旦从服务有数据写入,就会造成数据不一致。并且从服务在执行事务期间还很容易造成数据同步失败。

如果需要限制用户写数据,我们可以在从服务中将read_only参数的值设为1(setglobal read_only=1;)。这样就可以限制用户写入数据。但是这个属性有两个需要注意的地方:

1、read_only=1设置的只读模式,不会影响slave同步复制的功能。 所以在MySQL slave库中设定了read_only=1后,通过 “show slave status\G” 命令查看salve状态,可以看到salve仍然会读取master上的日志,并且在slave库中应用日志,保证主从数据库同步一致;

2、read_only=1设置的只读模式, 限定的是普通用户进行数据修改的操作,但不会限定具有super权限的用户的数据修改操作。 在MySQL中设置read_only=1后,普通的应用用户进行insert、update、delete等会产生数据变化的DML操作时,都会报出数据库处于只读模式不能发生数据变化的错误,但具有super权限的用户,例如在本地或远程通过root用户登录到数据库,还是可以进行数据变化的DML操作; 如果需要限定super权限的用户写数据,可以设置super_read_only=0。另外如果要想连super权限用户的写操作也禁止,就使用”flush tables with read lock;”,这样设置也会阻止主从同步复制!

3、其他集群方式

我们到这里搭建出了一个一主一从的MySQL主从同步集群,具有了数据同步的基础功能。而在生产环境中,通常会以此为基础,根据业务情况以及负载情况,搭建更大更复杂的集群。

​ 例如为了进一步提高整个集群的读能力,可以扩展出一主多从。而为了减轻主节点进行数据同步的压力,可以继续扩展出多级从的主从集群。

​ 为了提高整个集群的高可用能力,可以扩展出多主的集群。

​ 我们也可以扩展出互为主从的互主集群甚至是环形的主从集群,实现MySQL多活部署。

​ 搭建互主集群只需要按照上面的方式,在主服务上打开一个slave进程,并且指向slave节点的binlog当前文件地址和位置。

我们这里是使用的最为传统的Binlog方式搭建集群,是基于日志记录点的方式来进行主从同步的。在这个实验中,Executed_Grid_Set一列,实际上就是另外一种搭建主从同步的方式,即GTID搭建方式。GTID的本质也是基于Binlog来实现的主从同步,只是他会基于一个全局的事务ID来标识同步进度。这个GTID全局事务ID是一个全局唯一、并且趋势递增的分布式ID策略。我们这里就不再去搭建了。