欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > Mysql实现主从复制、读写分离

Mysql实现主从复制、读写分离

2025/2/24 12:25:23 来源:https://blog.csdn.net/LiuCJ_20000/article/details/143789220  浏览:    关键词:Mysql实现主从复制、读写分离

一、MySql主从复制

MySQL数据库默认是支持主从复制的,不需要借助于其他的技术,我们只需要在数据库中简单的配置即可。

1.1 主从复制简介

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

二进制日志:

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

MySQL复制过程分成三步:

1). MySQL master 将数据变更写入二进制日志( binary log)

2). slave将master的binary log拷贝到它的中继日志(relay log)

3). slave重做中继日志中的事件,将数据变更反映它自己的数据

1.2 环境搭建

1.2.1 准备工作

这里需要提前准备好两台服务器,并且在服务器中安装MySQL!

  • 192.168.112.136 作为 mysql 的主机 master
  • 192.168.112.137 作为 mysql 的从机 slave

我这里是通过虚拟机进行搭建的(利用其克隆功能直接复制出一个主机/从机)。系统搭建过程可参考文章(虚拟机的安装、mysql的安装等):Linux系统相关操作

并且在两台服务器上做如下准备工作:

  • 防护墙开发 3306 端口号:

firewall-cmd --zone=public --add-port=3306/tcp --permanent

firewall-cmd --zone=public --list-ports

firewall-cmd --reload

  • 将两台服务器的Mysql启动起来

systemctl start mysqld 或者

/etc/init.d/mysql start

这里的启动方式根据自己的mysql安装方式来确定实际的启动方式,只要将数据库访问启动起来即可!

1.2.2 主库配置 master

进入主机服务器中(192.168.112.136)进行相关配置操作:


  • 修改Mysql数据库的配置文件** /etc/my.cnf**

在该配置文件下方增加配置信息:

#[必须] 启用二进制日志
log_bin=master-bin
#log_bin_index=master-bin.index

#[必须]服务器唯一ID(唯一即可)
server-id=200

#二进制日志的有效期

expire-logs-days=7

#不需要同步的数据库

binlog_ignore_db=mysql

binlog_ignore_db=information_schema

binlog_ignore_db=performation_schema

binlog_ignore_db=sys

#需要同步的数据库名字

binlog_do_db=mybatis

添加完成后保存退出,然后重启 主机中的 mysql 服务!

systemctl restart mysqld


  • 创建数据同步的用户并授权

这里需要在主机中登录mysql,然后进行授权操作:

Mysql 中的 用户授权方式:

  • 用户授权 基本语法:

GRANT 权限列表(如:select、insert、update、drop…) ON 数据库名.表名 TO ‘登录用户名’@’ 远程登录的主机地址’ identified by ‘密码’ WITH GRANT OPTION;

  • 刷新权限

flush privileges;

这里需要创建一个 用户 ,并且 给该用户 授予 REPLICATION SLAVE 权限。常用于建立复制时所需要用到的用户权限,也就是从机slave必须被主机master授权具有该权限的用户,才能通过该用户复制。

GRANT REPLICATION SLAVE ON *.* to 'masterUser'@'%' identified by 'lcjMysql123..' with grant option;-- 刷新权限!
flush privileges;-- 这里创建了一个用户 masterUser  密码为 lcjMysql123..
-- 并且赋予了 PEPLICATION SLAVE (主从复制)权限! 
-- 以上%可以改为主机名,如果是%表示所有人都可以连接
-- 其中的 * 表示所有的 数据库或表-- 这里额外还需要注意的是,我们还需要给root用户授予远程连接支持的权限,方便后续对数据进行远程连接的操
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' identified by 'root密码' WITH GRANT OPTION;
-- 这里 ALL PRIVIEGES 直接赋予所有权限!

  • 登录Mysql数据库 查看 master 同步状态信息

进入mysql后 通过 sql:show master status; 查看 File 和 Position 的值! 这两个值需要记住,后续在从机中需要进行关联操作!

这里通过 show variables like '%log_bin%'; 可以观察到日志是否成功开启:

1.2.3 从库配置 slave

进入从机服务器中(192.168.112.137)进行相关配置操作:


  • 修改从库 Mysql 的配置文件/etc/my.cnf

[必须] 服务器唯一id
server-id = 2

#relay-log = slave-relay-bin

#relay-log-index = slave-relay-bin.index

在从数据库的配置文件中,只需要添加 服务器唯一Id即可:server-id=201 #[必须]服务器唯一ID

添加配置信息完成后,重启从机中的 Mysql服务即可!


  • 登录从库服务器的Mysql数据库,配置主库地址以及同步位置

 change master to master_host='192.168.112.136',master_port=3306,master_user='masterUser',master_password='lcjMysql123..',master_log_file='master-bin.000001',master_log_pos=1224;-- 启动slave;
start slave;-- 停止slave;
stop slave;

参数说明:

  1. master_host : 主库的IP地址
  2. master_user : 访问主库进行主从复制的用户名(上面在主库创建的)
  3. master_password : 访问主库进行主从复制的用户名对应的密码
  4. master_log_file : 从哪个日志文件开始同步(上述查询master状态中展示的有)
  5. master_log_pos : 从指定日志文件的哪个位置开始同步(上述查询master状态中展示的有)

  • 查看从数据库的状态

通过命令 show slave status \G;

然后通过状态信息中的 Slave_IO_running 和 Slave_SQL_running 可以看出主从同步是否就绪,如果这两个参数全为Yes,表示主从同步已经配置完成!

PS: 这里 Slave_IO_Running:NO 就看下一小结的排查方案


Slave_IO_running: 负责从数据库 去 主数据库 读取二进制日志,并写入到从数据库的中继日志!

Slave_SQL_running:负责将中继日志转换成SQL语句后执行!

MySQL命令行技巧: \G : 在MySQL的sql语句后加上\G,表示将查询结果进行按列打印,可以使每个字段打印到单独的行。即将查到的结构旋转90度变成纵向;

1.2.3 Slave_IO_Running: No 问题排查

这是一个很常见的错误,大概排查原因有以下几种:

  1. 主服务器的网络不通,或者主服务器的防火墙拒绝了外部连接3306端口

首先在从服务器上执行ping程序,确定能ping通主服务器在从服务器上执行mysq的远程连接!

<font style="color:rgb(77, 77, 77);">[root@slave204 log]# mysql -urep -p -h 192.168.112.137 -P3306</font>

如果显示ERROR 1045 (28000): Access denied for user ‘test’@‘192.168.1.204’ (using password: YES) 则说明没问题!

  1. 在配置从服务器时,输错了ip地址和密码,或者主服务器在创建用户时写错了用户名和密码
  2. 在配置从服务器时,输错了主服务器的二进制日志信息
  3. [重点 这也是我这里一直为 NO 的原因]

原因:两台主从数据库的uuid相同了(直接克隆了linux服务器,然后配置主从数据库,一通操作,到最后启动从数据库,发现的这个问题)。

解决办法:

  • 使用 find / -iname "auto.cnf"; 命令查找数据库的auto.cnf 配置文件位置

  • 然后通过vi 命令,修改该配置文件中的uuid 即可

这里随便改掉以为就可以了,保证这个uuid与克略对象的mysql 的uuid不同就行!

  • 重新启动mysql服务
  • 登录mysql,然后重启 slave 服务 ,然后再查看 slave 状态信息。

1.3 测试主从复制

主从复制的环境,已经搭建好了,接下来,我们可以通过Navicat连接上两台MySQL服务器,进行测试。测试时,我们只需要在主库Master执行操作,查看从库Slave中是否将数据同步过去即可。

  • 在master中创建数据库 TestTempDb , 刷新slave查看是否可以同步过去

  • 在master的 TestTempDb 数据下创建user表, 刷新slave查看是否可以同步过去

  • 在master的user表中插入一条数据, 刷新slave查看是否可以同步过去

向主库中插入数据:

在从表中查询该表:

二、Mysql读写分离

2.1 读写分离简介

面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。 对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库和从库,主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。

画板

通过读写分离,就可以降低单台数据库的访问压力, 提高访问效率,也可以避免单机故障。

2.2 ShardingJDBC介绍

Sharding-JDBC定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

使用Sharding-JDBC可以在程序中轻松的实现数据库读写分离。

Sharding-JDBC具有以下几个特点:

  1. 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
  2. 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  3. 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。

Maven 依赖:

<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.0-RC1</version>
</dependency>

2.3 项目读写分离实现

数据库环境准备

  1. 这里需要在主从复制配置完成的 主库master 中创建出一个测试表( 会自动同步到 slaver 库中 )!

  1. 创建项目够,对应工程中的 Mapper、Service、Controller层编写好,这里就不演示编写过程了,同时构建好增删改查操作!

项目读写分离实现步骤:

  1. 首先在项目pom.xml 中增加 Sharding 的maven坐标依赖。

***注: **这里版本号选用4.0.0-RC1 ,选用了 4.1.1 版本可能会出现相关兼容性问题!(这里就不延展讨论!)

  1. 在application.yml 配置文件中增加数据源(master、slave)配置
spring:application:name: grdc_project  #应用项目名称# 该配置项的目的,就是如果当前项目中存在同名的bean,后定义的bean会覆盖先定义的。main:allow-bean-definition-overriding: true# ====== [数据库读写分离配置] ======shardingsphere:datasource:names:master,slave  #该名称可以随意定,下面保存一致即可# 配置主数据库master:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.112.136:3306/TestTempDb?characterEncoding=utf-8username: rootpassword: lcjMysql123..# 从数据源slave:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.112.137:3306/TestTempDb?characterEncoding=utf-8username: rootpassword: lcjMysql123..#读写分离配置masterslave:load-balance-algorithm-type: round_robin #轮询 , 如果有多个从库则采用负载均衡策略name: dataSource   # 最终的数据源名称master-data-source-name: master   # 主库数据源名称slave-data-source-names: slave    # 从库数据源名称列表,多个逗号分隔props:sql:show: true  #开启SQL显示,默认false

ps:注意

如果出现如下错误的情况:

***************************
APPLICATION FAILED TO START
***************************Description:The bean 'dataSource', defined in class path resource [org/apache/shardingsphere/shardingjdbc/spring/boot/SpringBootConfiguration.class], could not be registered. 
A bean with that name has already been defined in class path resource [com/alibaba/druid/spring/boot/autoconfigure/DruidDataSourceAutoConfigure.class] and overriding is disabled.Action:Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=trueProcess finished with exit code 1

需要在 yml 文件中配置

spring:  main:allow-bean-definition-overriding: true

该配置项的目的,就是如果当前项目中存在同名的bean,后定义的bean会覆盖先定义的。

报错信息表明,在声明 org.apache.shardingsphere.shardingjdbc.spring.boot 包下的SpringBootConfiguration中的dataSource这个bean时出错, 原因是有一个同名的 dataSource 的bean在com.alibaba.druid.spring.boot.autoconfigure包下的DruidDataSourceAutoConfigure类加载时已经声明了。

而我们需要用到的是 shardingjdbc包下的dataSource,所以我们需要配置上述属性,让后加载的覆盖先加载的。

2.3 测试

所有配置完成之后启动项目即可,我这里的 UserController 层封装了如下两个接口用于测试读写分离用!

我们可以通过debug及日志的方式来查看每一次执行增删改查操作,使用的是哪个数据源,连接的是哪个数据库。

  • 测试DML 操作:


插入一条数据时,是向 Master 主库进行写操作!

  • 测试DQL 操作:

[完结!]

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词