小公司里用 SpringBoot 做 MySQL 分库分表,踩了一些坑!
1、MySQL 主从复制
我们仔细观察我们会发现,当我们的项目都是用的单体数据库时,那么就可能会存在如下问题:
读和写所有压力都由一台数据库承担, 压力大
数据库服务器磁盘损坏则 数据丢失 ,单点故障
为了解决上述提到的两个问题,我们可以准备两 (多) 台 MySQL,一台主( Master )服务器,一台从( Slave )服务器,主库的 数据变更 (写、更新、删除这些操作) ,需要 同步 到从库中 (主从复制) 。
而用户在访问我们项目时,如果是 写操作 (insert、update、delete),则直接操作 主库 ; 如果是 读操作 (select) ,则直接操作从库,这种结构就是 读写分离 啦。
在这种读写分离的结构中,从库是可以有多个的
1.1、介绍
MySQL 主从复制是一个 异步 的复制过程,底层是基于 Mysql 数据库自带的 二进制日志 功能。 就是一台或多台 MySQL 数据库(slave,即 从库 )从另一台 MySQL 数据库(master,即 主库 )进行日志的复制,然后再解析日志并应用到自身,最终实现 从库 的数据和 主库 的数据保持一致。
MySQL 主从复制是 MySQL 数据库自带功能,无需借助第三方工具。
二进制日志:
二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言)语句,但是不包括数据查询语句。 此日志对于灾难时的数据恢复起着极其重要的作用,MySQL 的主从复制, 就是通过该 binlog 实现的。 默认 MySQL 是未开启该日志的。
MySQL 复制过程分成三步:
MySQL master 将数据变更写入二进制日志( binary log )
slave 将 master 的 binary log 拷贝到它的中继日志( relay log )
slave 重做中继日志中的事件,将数据变更反映它自己的数据
1.2、主从库搭建
在环境搭建之前,我们需要准备好两台服务器,如果生活富裕使用的是两台云服务器的时候记得要开放安全组,即防火墙; 如果是比狗子我生活好点但也是用的虚拟机的话,记得别分这么多内存启动蓝屏了(别问怎么知道的)
这里就不给大家展示数据库的安装和防火墙的操作了,这个我感觉网上好多资源都能够满足遇到的问题,在搭建主从库的时候有在网上见到过说 MySQL 版本要一致的,我也没太留意直接就在之前的 MySQL 上操作了,大家可以自己去验证一下。
1.2.1、主库配置
服务器: 192.168.150.100(别试了黑不了的,这是虚拟机的 ip)
1、修改 Mysql 数据库的配置文件 vim /etc/my.cnf
2、重启 Mysql 服务
这里有三个方 法都能重启 MySQL,最简单的无疑就是一关一开:
3、创建数据同步的用户并授权
登录进去 MySQL 之后才能够执行下面的命令,因为这是 SQL 命令,Linux 不认识这玩意是啥。
4、查看 master 同步状态
这个时候还 不用退出 MySQL ,因为下面的命令还是 SQL 命令,执行下面的 SQL,可以拿到我们后面需要的两个重要参数。
执 行完这一句 SQL 之后,==不要再操作主库! 不要再操作主库! 不要再操作主库! ==重要的事情说三遍,因为再操作主库之后可能会导致红框中的 两个属性值会发生变化 ,后面如果发生了错误可能就和这里有那么两毛钱关系了。
1.2.2、从库配置
服务器: 192.168.150.101(别试了黑不了的,这也是虚拟机的 ip)
1、 修改 Mysql 数据库的配置文件 vim /etc/my.cnf
这里要注意 server-id 和主库以及其他从库都不能相同,否则后面将会配置不成功。
2、重启 Mysql 服务
这里有三个方法都能重启 MySQL,最简单的无疑就是一关一开:
3、设置主库地址及同步位置
登录进去 MySQL 之后才能够执行下面的命令,因为这是 SQL 命令
参数说明:
master_host: 主库的 IP 地址
master_user: 访问主库进行主从复制的 用户名 ( 上面在主库创建的 )
master_password: 访问主库进行主从复制的用户名对应的 密码
master_log_file: 从哪个 日志文件 开始同步 ( 即 1.2.1 中第 4 步获取的 File )
master_log_pos: 从指定日志文件的哪个 位置 开始同步 ( 即 1.2.1 中第 4 步获取的 Position )
4、查看从数据库的状态
这个时候还 不用退出 MySQL ,因为下面的命令还是 SQL 命令,执行下面的 SQL,可以看到从库的状态信息。 通过状态信息中的 Slave_IO_running 和 Slave_SQL_running 可以看出主从同步是否就绪,如果这两个参数全为 Yes ,表示主从同步已经配置完成。
1.3、坑位介绍
1.3.1、UUID 报错
这可能是由于 linux 是复制出来的,MySQL 中还有一个 server_uuid 是一样的,我们也需要修改。 vim /var/lib/mysql/auto.cnf
1.3.2、server_id 报错
这应该就是各位大牛设置 server_id 的时候不小心设置相同的 id 了,修改过来就行,步骤在上面的配置中。
1.3.3、同步异常解决
这是狗子在操作过程中搞出来的一个错误……
出错的原因是在主库中删除了用户信息,但是在从库中同步的时候失败导致同步停止,下面记录自己的操作(是在进入 MySQL 的操作且是从库)。
在数据库中操作时,一定要注意当前所在的数据库是哪个,作为一个良好的实践:在 SQL 语句前加 USE dbname
。
操作不规范,亲人两行泪……
2、项目中实现
2.1、ShardingJDBC
Sharding-JDBC 定位为 轻量级 Java 框架 ,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包 形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动, 完全兼容 JDBC 和各种 ORM 框架 。
使用 Sharding-JDBC 可以在程序中轻松的实现数据库 读写分离 。
Sharding-JDBC 具有以下几个特点:
适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC。
支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP 等。
支持任意实现 JDBC 规范的数据库。目前支持 MySQL,Oracle,SQLServer,PostgreSQL 以及任何遵循 SQL92 标准的数据库。
下面我们将用 ShardingJDBC 在项目中实现 MySQL 的读写分离。
2.2、依赖导入
在 pom.xml 文件中导入 ShardingJDBC 的依赖坐标
2.3、配置文件
在 application.yml 中增加数据源的配置
2.4、测试跑路
这时我们就可以对我们项目中的配置进行一个测试,下面分别调用一个更新接口和一个查询接口,通过查看日志中记录的数据源来判断是否能够按照我们预料中的跑。
更新操作(写操作)
查询操作(读操作)
搞定! ! ! 程序正常按照我们预期的成功跑起来了,成功借助 ShardingJDBC 在我们项目中实现了数据库的读写分离。
评论