Java开发 - MySQL主从复制初体验

前言

前面已经学到了很多知识,大部分也都是偏向于应用方面,在应用实战这条路上,博主一直觉得只有实战才是学习中最快的方式。今天带来主从复制给大家,在刚刚开始动手写的时候,才想到似乎忽略了一些重要的东西,不过还好,既然想到了,就会在本文中体现出来,争取让大家学完之后明白主从复制的原理和怎么去做主从复制。

什么是主从复制

MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的 二进制日志 功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制,然后再解析日志并应用到自身,最终实现 从库 的数据和 主库 的数据保持一致。MySQL主从复制是MySQL数据库自带功能,无需借助第三方工具。

​二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言)语句,但是不包括数据查询语句。此日志对于灾难时的数据恢复起着极其重要的作用,MySQL的主从复制, 就是通过该binlog实现的。默认MySQL是未开启该日志的。

主从复制分为三步完成:

  • MySQL master 将数据变更的SQL语句写入二进制日志( binary log)
  • slave将master的binary log拷贝到它的中继日志(relay log),说是拷贝,其实是读取过来,也可以理解成拷贝,内容拷贝
  • slave读取中继日志中的事件,将数据变更反映它自己的数据库中

Docker模拟多服务器准备

博主没有办法在真正的两台云端服务器上给大家做演示,所以就在本地给大家模拟一下做法,有虚拟机的使用虚拟机复制出来一个使用,没有虚拟机的可以使用Docker来模拟。

使用Docker模拟时,需要创建两个mysql的容器:

Master(主):

docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql

Slave(从):

docker run -p 3309:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 -d mysql

博主没有指定版本,因为博主Image内已经存在一个最新的版本,如果使用的版本略低,可手动指定: 

docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:x.x.x

这里需要说明一下端口,由于非生产环境,本地模拟时,端口需要映射,不能全都用3306,所以slave中映射了3309,否则容器启动会因为端口冲突报错。

此时在Docker内,已经有两个运行中的mysql了:

Java开发 - MySQL主从复制初体验_第1张图片

docker ps可以查看运行中的容器:

Java开发 - MySQL主从复制初体验_第2张图片

配置数据库主从

配置Master

docker exec -it 8e46c78ba828 /bin/bash

输入上面的命令,进入master容器内部,8e46c78ba828是容器id,也可以使用容器名mysql进入:

docker exec -it mysql /bin/bash

输入:

cd /etc/mysql

进入mysql的配置文件目录下,对my.cnf进行编辑:

vi my.cnf

正常是会报错的,会提示:

bash: vi: command not found

需要我们在docker内安装vim,这个我们在前面的博客中有提到,为了方便,此处再写一下解决步骤:

输入

apt-get install vim

提示:

Reading package lists... Done

Building dependency tree       

Reading state information... Done

E: Unable to locate package vim

输入

apt-get update

 Java开发 - MySQL主从复制初体验_第3张图片

然后输入

apt-get install vim

等待vim安装完成即可。

Java开发 - MySQL主从复制初体验_第4张图片

注意里面会有一个提示,输入Y。安装过程可能会有点慢,稍安勿躁。

安装完成,此时再输入以下命令:

vi my.cnf

在最下面增加配置:

log-bin=mysql-bin   #[必须]启用二进制日志
server-id=100       #[必须]服务器唯一ID(唯一即可)

然后退出保存即可。下面要重启mysql服务,让配置生效:

你可以选择使用命令行

service mysql restart

甚至你还需要重启mysql容器:

docker start mysql

但博主这里偷懒,直接在docker内部重启mysql容器,哈哈!!!

特别注意:你目前所在的文件夹是:root@8e46c78ba828:/etc/mysql

你需要通过两次cd ..回到顶端目录,然后使用:

mysql -uroot -pxxxx

u后面跟账号,p后面跟密码,登录到mysql内:

Java开发 - MySQL主从复制初体验_第5张图片

以上启动sql的命令运行在root@8e46c78ba828:/etc/mysql目录下是不行的,需要你退出docker容器运行才可以,这个是常识哈,我当大家都知道的。

下一步在Master数据库创建数据同步用户,授予slave的访问用户,比如slave,授权 REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据,分两步完成:

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

Java开发 - MySQL主从复制初体验_第6张图片

到这里,主库的配置就算是完成了,你可以输入:

show master status;

 来查看主库的状态:Java开发 - MySQL主从复制初体验_第7张图片此时主库什么都不要动,这里的File和Position我们后面有用。

配置Salva

接下来我们来配置从库,整体步骤和主库差不多,但是为了让大家不出错,这里还是一步步带着大家操作。

首先新开一个终端窗口:

docker exec -it e2476006aeb4 /bin/bash

输入上面的命令,进入slave容器内部,e2476006aeb4是容器id,也可以使用容器名mysql-slave进入:

docker exec -it mysql-slave /bin/bash

输入:

cd /etc/mysql

进入mysql的配置文件目录下,对my.cnf进行编辑:

vi my.cnf

不出意外的又报错了,还是和主库一样,这是因为两个容器互不相关,所以还需要在此容器安装vim,步骤一样,大家照着上面来。

安装完成,此时再输入以下命令:

vi my.cnf

在最下面增加配置:

log-bin=mysql-bin   #[必须]启用二进制日志
server-id=101       #[必须]服务器唯一ID(唯一即可)

然后退出保存即可。下面要重启mysql服务和容器,让配置生效。这里注意,id变了,主库是100,此处是101。

关联主从数据库

进入从数据库中,登陆了从数据库,执行以下命令,设置主库地址及同步位置

change master to master_host='172.17.0.2',master_user='slave',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=721;

来解释下这里的数据来源。

ip通过以下命令获得:

docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器id/容器名

master_log_file='mysql-bin.000001',master_log_pos=721;还记得我们通过show master status获得的表格吗?

Java开发 - MySQL主从复制初体验_第8张图片

看看数据对不对的上。

然后执行:

start slave;

为了验证主从关联是否完成,在从库Slave中输入以下命令:

show slave status \G;

\G是因为让显示是一行一行的,否则表格太长,无法直观的看到想要的信息。 

查看SlaveIORunning 和 SlaveSQLRunning 都是Yes,说明主从复制已经开启。

Java开发 - MySQL主从复制初体验_第9张图片

 此时,SlaveIORunning一直是Connecting,则说明主从复制一直处于连接状态,查看错误:

error connecting to master '[email protected]:3306' - retry-time: 60 retries: 1 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.

提示我们授权有问题,详情可查看此篇博客:Authentication plugin 'caching_sha2_password' reported error:Authentication..我们采用这篇博客说的第三种办法去解决这个问题,避免使用caching_sha2_password插件,所以我们需要重新创建一个用户:

CREATE USER 'repl'@'%' IDENTIFIED WITH 'mysql_native_password' BY '123456';

前面做的时候没有做远程授权,也会报错,所以这里加上了授权远程访问的权限: 

GRANT ALL PRIVILEGES ON *.* TO 'repl'@'%'  WITH GRANT OPTION;

我们查看下数据库中用户的列表:

Java开发 - MySQL主从复制初体验_第10张图片

一定要有远程访问的权限才可以,Grant_priv就是,虽然slave用户也授权了远程权限,但是使用了caching_sha2_password,也不可用,所以才新建了repl用户。接着,我们要查看主库的状态,重新获取关键信息:

show master status;

查看主库状态:

Java开发 - MySQL主从复制初体验_第11张图片

发现原来的 721变了,File的文件后缀名也变为02了。这里要注意,一定要用新的,到这里,主库千万不要再去动了,否则会出别的问题。

下面在从库重新关联主从,在这之前,需要先停止slave:

stop slave;
reset slave;

然后执行此命令关联:

change master to master_host='172.17.0.2',master_user='repl',master_password='123456',master_log_file='mysql-bin.000002',master_log_pos=2819;

注意参数改为2819,接着启动slave:

start slave;

 查看关联状态:

show slave status \G;

Java开发 - MySQL主从复制初体验_第12张图片

看到两个YES,就说明主从已经配置好了。  

关于mysql的授权相关命令,推荐一篇博客给大家:MySql 授权命令grant

测试主从

我们在使用Docker内部IP访问数据库的时候发现无法连接,这是因为这个IP是docker内部id,博主查了很多资料,都没有很好的解决这个问题,但是,也看到了一些说法:

如何访问docker容器ip-Docker-PHP中文网

根据这篇博客,最终得到的结论就是,虽然无法直接访问docker内部ip,但是我们已经通过端口映射到了localhost的端口上,所以,可以把docker内部ip地址换成主机地址,也可以直接用localhost,port使用映射的端口就可以。

还有另一篇博客:

 解决docker宿主机不能访问容器的问题_docker宿主机访问不到容器 

这篇博客提出在创建容器的时候,容器与宿主机共享同一个网卡,不过博主没有重新创建容器,有兴趣的小伙伴自行尝试。 

此时我们通过localhost链接主从数据库,由于主数据库源本来就存在其他的数据库,从库是新的,连接上之后,完全没有问题,俩数据库绝对是完全不一样的,我们使用localhost的做法也是正确的,这位我们测试主从提供了良好的环境。

下面开始测试,在主数据库创建数据库,并创建新表:

create database if not exists master_slave character set utf8;
use master_slave;
CREATE TABLE user (
            id bigint(20) primary key auto_increment,
            username varchar(32) not null,
            password  varchar(32) not null,
            age int(3) not null ,
            phone varchar(32) not null
)

Java开发 - MySQL主从复制初体验_第13张图片

 此时用户表已经创建完毕,我们去从库看一下这个表有没有被创建出来:

Java开发 - MySQL主从复制初体验_第14张图片

从库里面已经出现了数据库和用户表,非常棒,主从完美啊,我们在主库用户表添加点数据看看: 

insert into user value(null ,'codingfire','123456',20,'13812345678');

查看主库表:

Java开发 - MySQL主从复制初体验_第15张图片

用户信息已经插入,切换到从库查看:

Java开发 - MySQL主从复制初体验_第16张图片

从库也有了,主从复制测试成功。删除修改大家可以自行测试。 

注意:细心点,你会发现页面左上角的数据库连接对象是不一样的,所以这里连接docker使用localhost是完全没有问题的。另外,如果docker异常关机等,导致同步的游标出现错乱,需要重新配置日志游标:

stop slave;
change master to master_log_file='mysql-bin.00000x', master_log_pos=xxxx;
start slave;

结语

总的来说,mysql的主从还是没那么复杂的,没有代码操作,全都是配置,在真实的服务器上,配置也基本都是这样,这里学会了,真实的服务器也不在话下。虽然主从复制写完了,但是关于主从的只是只是还没有结束,因为还没在项目中引入主从的使用,下一篇,我们将学习主从在项目中的使用——读写分离。觉得不错,就给博主个赞吧。

你可能感兴趣的:(Java之微服务系列,mysql,主从复制,数据库主从复制,主从,数据库主从)