主从架构意义


通过搭建MySQL主从集群,可以缓解MySQL的数据存储以及访问的压力。


1:数据安全


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


于主从架构搭建互主的架构。



2:读写分离,

     对于大部分的JAVA业务系统来说,都是读多写少的,读请求远远高于写请求。这



时,当主服务的访问压力过大时,可以将数据读请求转为由从服务来分担,主服务



只负责数据写入的请求,这样大大缓解数据库的访问压力。 要理解,MySQL的主从架构只是实现读写分离的一个基础。实现读写分离还是需 要一些中间件来支持,比如ShardingSphere。



3: 故障转移-高可用



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



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



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




同步的原理


          MySQL服务的主从架构一般都是通过binlog日志文件来进行的。即在主服务上打

开binlog记录每一步的数据库操作,然后从服务上会有一个IO线程,负责跟主服务

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


mysql可视化 mac_mysql


        MySQL的binlog不光可以用于主从同步,还可以用于缓存数据同步等场景。 例如Canal,可以模拟一个slave节点,向MySQL发起binlog同步,然后将数据落地到Redis、Kafka等其他组件,实现数据实时流转、



搭建主从集群时,有两个必要的要求:

1:双方MySQL必须版本一致。至少需要主服务的版本低于从服务

2:两节点间的时间需要同步。

搭建主从架构

我们直接使用docker搭建mysql主从架构,首先配置master节点

配置Master节点

创建目录,以及目录下的文件

mkdir /mydata/MHA/master

mysql可视化 mac_架构_02

在conf目录下创建配置文件

[mysqld]
server-id=47
#开启binlog
log_bin=master-bin
log_bin-index=master-bin.index
skip-name-resolve
#设置连接端口
port=4306
#设置mysql数据库的数据的存放目录
datadir=/var/lib/mysql-files
#允许最大连接数
max_connections=200
#允许连接失败的次数。
max_connect_errors=10
#服务端使用的字符集默认为UTF8
character-set-server=utf8
#创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
#默认使用“mysql_native_password”插件认证
#mysql_native_password
default_authentication_plugin=mysql_native_password

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

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

log_bin-index:Binlog日志文件


启动mysql master主节点

docker stop mysqlMaster && docker rm mysqlMaster
docker run  --restart=always --privileged=true \
-p 4306:4306 \
--name mysqlMaster \
-v /mydata/MHA/master/data:/var/lib/mysql-files \
-v /mydata/MHA/master/conf/my.cnf:/etc/mysql/my.cnf \
-v /mydata/MHA/master/conf/conf.d:/etc/mysql/conf.d \
-v /mydata/MHA/master/logs:/var/log/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-e TZ=Asia/Shanghai \
-d mysql:8.0.28

给root用户分配一个replication slave的权限。

mysql  
  -u  
  root  
  -p 
 
 
初始没有密码直接登陆
 
 
赋予用户其他主机可以登陆的权限以及密码
 
 
CREATE USER  'root'@'ip地址/主机名' IDENTIFIED BY '密码';
 
 

   mysql> grant all privileges on *.* to 'username'@'%'; //赋权限,%表示所有(host) 
  
   
  
 
GRANT  REPLICATION SLAVE ON *.* TO   
  'root' 
  @ 
  '%' 
  ;
 
 

 
 
#刷新权限
 
 
flush privileges; 

   更新用户的信息 
 
 
 

   use mysql; 
 
 
 

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



# 查看主节点同步状态:

show master status;

mysql可视化 mac_数据库_03

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

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




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


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

可以查看我们映射目录data下的bin文件

mysql可视化 mac_数据库_04

 配置Slave从节点

和上面创建master节点目录一样,创建slave目录

mysql可视化 mac_mysql_05

 创建my.cnf文件

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

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

server-id:服务节点的唯一标识 
 
 
relay-log:打开从服务的relay-log日志。 
 
 
log-bin:打开从服务的bin-log日志记录。

启动slave节点:并设置他的主节点同步状态。

docker stop mysqlSlave && docker rm mysqlSlave
 docker run  --restart=always --privileged=true \
 -p 4307:4306 \
 --name mysqlSlave \
 -v /mydata/MHA/slave/data:/var/lib/mysql-files \
 -v /mydata/MHA/slave/conf/my.cnf:/etc/mysql/my.cnf \
 -v /mydata/MHA/slave/conf/conf.d:/etc/mysql/conf.d \
 -v /mydata/MHA/slave/logs:/var/log/mysql \
 -e MYSQL_ROOT_PASSWORD=root \
 -e TZ=Asia/Shanghai \
 -d mysql:8.0.28        
[root@node01 MHA]# docker exec -it mysqlSlave bash
 root@3b072fba3bd9:/# mysql -uroot -proot
 mysql: [Warning] Using a password on the command line interface can be insecure.
 Welcome to the MySQL monitor.  Commands end with ; or \g.
 Your MySQL connection id is 10
 Server version: 8.0.28 MySQL Community Server - GPLCopyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
 affiliates. Other names may be trademarks of their respective
 owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> 
# 
  设置同步主节点: 
 
 
CHANGE MASTER TO 
 
 
MASTER_HOST 
  = 
  'node01' 
  , 
 
 
MASTER_PORT 
  =4 
  306 
  , 
 
 
MASTER_USER 
  = 
  'root' 
  , 
 
 
MASTER_PASSWORD 
  = 
  'root' 
  , 
 
 
MASTER_LOG_FILE 
  = 
  'master-bin.000003' 
  , 
 
 
MASTER_LOG_POS 
  = 
  157,
 
 
GET_MASTER_PUBLIC_KEY 
  = 
  1 
  ; 
 
 
# 
  开启 
  slave 
 
 
start  
  slave; 
 
 
# 
  查看主从同步状态 
 
 
show slave status; 
 
 
或者用  
  show slave status \G;  
  这样查看比较简洁



注意,CHANGE MASTER指令中需要指定的MASTER_LOG_FILE和 MASTER_LOG_POS必须与主服务中查到的保持一致。 并且后续如果要检查主从架构是否成功,也可以通过检查主服务与从服 务之间的File和Position这两个属性是否一致来确定。


mysql可视化 mac_MySQL_06

 我们重点关注的就是红框内的数据,其中     Master_Log_File: master-bin.000003
   Read_Master_Log_Pos: 157 与主节点保持一致就是正确的,其中        Slave_IO_Running: Yes
Slave_SQL_Running: Yes

yes表示主节点和从节点都是运行状态



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




主从集群测试


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





mysql可视化 mac_数据库_07


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

mysql可视化 mac_MySQL_08


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



 

mysql可视化 mac_MySQL_09

可以看到从库里是 多了一个testdemo数据库,表示数据库已经同步过去了。


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



mysql可视化 mac_mysql可视化 mac_10


 看看从库的数据表是否也同步成功:

mysql可视化 mac_MySQL_11

 在从库 testdemo库中可以看到新增了一个表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的文件和位置,如果修改后和之前的同步接 不上,那就会丢失部分数据。所以不太常用。