MySQL服务器只有一台会存在以下问题:
- 读和写所有压力都由一台数据库承担,压力大 ----- 没有实现扩容
- 数据库服务器磁盘损坏则数据丢失,单点故障-------没有实现高可用
解决方案:
准备两台MySQL,一台主(Master)服务器,一台从(Slave)服务器,主库的数据变更,需要同步到从库中(主从复制)。而用户在访问我们项目时,如果是写操作(insert、update、delete),则直接操作主库;如果是读(select)操作,则直接操作从库(在这种读写分离的结构中,从库是可以有多个的),这种结构我们称为 读写分离
一、MySQL主从复制
MySQL数据库默认支持主从复制,只需数据库进行配置下即可完成。
主从复制:MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的 二进制日志 功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制,然后再解析日志并应用到自身,最终实现 从库 的数据和 主库 的数据保持一致。MySQL主从复制是MySQL数据库自带功能,无需借助第三方工具。
复制流程:
-
MySQL master 将数据变更写入二进制日志( binary log),只要主节点有数据改变都会向binlog写入数据。
-
slave会从节点监听设置监听binary log,将master的binary log拷贝到它的中继日志(relay log),
-
slave重做中继日志中的事件,将数据变更反映它自己的数据
1.主库配置
-
修改Mysql数据库的配置文件/etc/my.cnf
-
vim /etc/my.cnf
-
在配置文件最下面添加配置
-
log-bin=mysql-bin #[必须]启用二进制日志 server-id=130 #[必须]服务器唯一ID(唯一即可)
-
-
重启Mysql服务
-
systemctl restart mysqld
-
创建数据同步的用户并授权登录
# 登录: mysql -uroot -proot #授权 GRANT REPLICATION SLAVE ON *.* to 'xiaoming'@'%' identified by 'Root@123456'; #刷新权限 flush privileges;
- xiaoming 代表用户名,Root@123456为密码
- 建立复制时所需要用到的用户权限,也就是slave必须被master授权具有该权限的用户,才能通过该用户复制。
-
登录Mysql数据库,查看master同步状态
-
show master status;
-
记录下结果的file和position,后面slave需要用到
-
2.从库配置
如果是从本地复制的centos系统,需要删除节点id配置,因为复制的两个节点id是一样的,要保证两个id不一样。
# 停止mysql
systemctl stop mysqld
# 删除 mysql从节点的uuid配置
rm -rf /var/lib/mysql/auto.cnf
# 启动mysql
systemctl start mysqld
-
修改Mysql数据库的配置文件/etc/my.cnf
-
vim /etc/my.cnf
-
server-id=132 #[必须]服务器唯一ID # 需要配置跳过错误,否则遇到错误,主从复制会停止 slave_skip_errors=all # 这个必须加上
-
-
重启mysql服务
systemctl restart mysqld
- 登录Mysql数据库,设置主库地址及同步位置
- master_host : 主库的IP地址
- master_user : 访问主库进行主从复制的用户名(上面在主库创建的)
- master_password : 访问主库进行主从复制的用户名对应的密码
- master_log_file : 从哪个日志文件开始同步(上述查询master状态中展示的有)
- master_log_pos : 从指定日志文件的哪个位置开始同步(上述查询master状态中展示的有)
# 登录:
mysql -uroot -proot
# 停止
stop slave;
# 设置主库地址及同步位置: 修改成自己的主库 ip 、 master_log_pos
change master to master_host='192.168.46.130',master_user='xiaoming',master_password='Root@123456',master_log_file='mysql-bin.000002',master_log_pos=781;
#启动
start slave;
-
查看从库状态
show slave status\G; # \G :表示将查询结果进行按列打印,可以使每个字段打印到单独的行
- 通过状态信息中的 Slave_IO_running 和 Slave_SQL_running ,可以看出主从同步是否开启,如果这两个参数都为yes,表示主从同步配置完成。
idea连接数据库如果报错,就在url加上?useSSL=false&allowPublicKeyRetrieval=true
# jdbc:mysql://自己的IP:3306/?useSSL=false&allowPublicKeyRetrieval=true
jdbc:mysql://192.168.33.132:3306/?useSSL=false&allowPublicKeyRetrieval=true
3.数据库集群主从复制作用
- 能够避免单点故障: 不会因为一台mysql服务器挂掉,导致整个项目不能正常访问;
- 能够实现读写分离效果: 减轻每个节点的压力;
二、实现读写分离
1.ShardingJDBC
ShardingJDBC:定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
使用Sharding-JDBC可以在程序中轻松的实现数据库读写分离。
特点:
- 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
- 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
- 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。
ShardingJDBC主要作用:
- 实现数据库读写分离
- 常见的分布式数据库中间件
2. 读写分离配置
- 引入shardingJdbc的maven坐标
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
- 配置yml文件数据源的配置
spring:
shardingsphere:
datasource:
names:
master,slave
# 主数据源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.200.200:3306/rw?characterEncoding=utf-8
username: root
password: root
# 从数据源
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.200.201:3306/rw?characterEncoding=utf-8
username: root
password: root
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
- 允许定义相同的bean对象
spring:
main:
allow-bean-definition-overriding: true
这个配置主要是声明spring框架是否允许定义重名的bean对象覆盖原有的bean
( spring boot默认是false )
- 如果不配置,项目启动可能报错