目录
搭建mysql主从数据库
Springboot应用搭建
pom依赖
application.properties配置
测试
开启日志(非必须)
ShardingSphere-JDBC 定位为轻量级的分布式数据库中间件解决方案,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。
功能特性:
可参考之前的文章,《【mycat系列一】基于 Docker 搭建 MySQL 主从复制的详细教程》搭建一主两从的mysql,当然你也可以不使用docker,使用多台linux搭建,详细信息如下:
数据库类型 | 数据库 | docker容器中IP | 宿主机IP(对外IP) |
---|---|---|---|
主:mysql-master | test | 172.17.0.2:3306 | 192.168.239.128:3307 |
从:mysql-slave1 | test | 172.17.0.3:3306 | 192.168.239.128:3308 |
从:mysql-slave2 | test | 172.17.0.4:3306 | 192.168.239.128:3309 |
配置好主从后,在主库创建一个新的数据库test,可使用Navicat等第三方客户端工具,或者命令行脚本都可以,SQL脚本如下:
USE `test`;
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT '' COMMENT '名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1307873057269878786 DEFAULT CHARSET=utf8 COMMENT='用户表';
Navicat效果如下:
本文,将整合 SpringBoot + Mybatis-plus + Druid + Sharding-JDBC + MySQL,具体如下:
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
true
mysql
mysql-connector-java
5.1.38
com.alibaba
druid
1.1.22
io.shardingsphere
sharding-jdbc-spring-boot-starter
3.1.0.M1
com.baomidou
mybatis-plus-boot-starter
3.1.2
com.baomidou
mybatis-plus-generator
3.1.2
# 服务端口
server.port=8080
# mysql-plus 配置
mybatis-plus.mapper-locations=classpath:/mapper/*.xml
mybatis-plus.type-aliases-package=com.stwen.shardingjdbc.entity
spring.main.allow-bean-definition-overriding=true
# sharding-jdbc 配置主从
sharding.jdbc.dataSource.names=master,slave1,slave2
# sharding-jdbc 主数据库
sharding.jdbc.dataSource.master.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.dataSource.master.driverClassName=com.mysql.jdbc.Driver
sharding.jdbc.dataSource.master.url=jdbc:mysql://192.168.239.128:3307/test?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
sharding.jdbc.dataSource.master.username=root
sharding.jdbc.dataSource.master.password=123456
sharding.jdbc.dataSource.master.maxPoolSize=20
# sharding-jdbc 从数据库一
sharding.jdbc.dataSource.slave1.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.dataSource.slave1.driverClassName=com.mysql.jdbc.Driver
sharding.jdbc.dataSource.slave1.url=jdbc:mysql://192.168.239.128:3308/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT
sharding.jdbc.dataSource.slave1.username=root
sharding.jdbc.dataSource.slave1.password=123456
sharding.jdbc.dataSource.slave1.maxPoolSize=20
# sharding-jdbc 从数据库二
sharding.jdbc.dataSource.slave2.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.dataSource.slave2.driverClassName=com.mysql.jdbc.Driver
sharding.jdbc.dataSource.slave2.url=jdbc:mysql://192.168.239.128:3309/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT
sharding.jdbc.dataSource.slave2.username=root
sharding.jdbc.dataSource.slave2.password=123456
sharding.jdbc.dataSource.slave2.maxPoolSize=20
# 配置从库选择策略,提供轮询与随机,这里选择用轮询,random-随机
sharding.jdbc.config.masterslave.load-balance-algorithm-type=round_robin
# 配置主从读写分离
sharding.jdbc.config.masterslave.name=master-slave
sharding.jdbc.config.masterslave.master-data-source-name=master
sharding.jdbc.config.masterslave.slave-data-source-names=slave1,slave2
# 开启SQL显示,默认值: false,注意:仅配置读写分离时不会打印日志
sharding.jdbc.props.sql.show=true
配置参数说明:
其他的详细参数就不一一解释了,简单看一下就明白。
其中,spring.main.allow-bean-definition-overriding=true 是防止报如下错误而添加的:
在Springboot启动类,增加配置,mybatis的dao接口包扫描,如下
编写测试类,增加两个接口:新增、查询列表
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@PutMapping("/save")
public Object save() {
User user = new User();
user.setName("新增");
return userService.save(user);
}
@GetMapping("/list")
public Object list() {
// 强制路由主库
//HintManager.getInstance().setMasterRouteOnly();
return userService.list();
}
}
启动应用,访问接口:localhost:8080/user/save ,可以查看数据,发现新增了一条数据
再访问列表查询接口:localhost:8080/user/list
(非必须)开启sql语句的日志,生产环境不建议开启,这里只是为了验证是否达到读写分离的效果。
查看日志目录,并开启sql语句的日志:
mysql> show variables like '%general_log%';
mysql> set global general_log=on;
注:
3个数据库都设置之后,再次访问两个测试接口,再来查看sql日志:
如下,在mysql-master 容器中,查看sql日志,可以看到插入的sql在主数据库执行
如下,查看mysql-slave2的sql日志,读取列表数据在从数据库执行,说明我们配置的读写分离是成功的。
主从同步延迟问题
读写分离架构中经常出现,那就是读延迟的问题如何解决?
刚插入一条数据,然后马上就要去读取,这个时候有可能会读取不到?归根到底是因为主节点写入完之后数据是要复制给从节点的,读不到的原因是复制的时间比较长,也就是说数据还没复制到从节点,你就已经去从节点读取了,肯定读不到。mysql5.7 的主从复制是多线程了,意味着速度会变快,但是不一定能保证百分百马上读取到,这个问题我们可以有两种方式解决:
(1)业务层面妥协,是否操作完之后马上要进行读取
(2)对于操作完马上要读出来的,且业务上不能妥协的,我们可以对于这类的读取直接走主库,当然Sharding-JDBC也是考虑到这个问题的存在,所以给我们提供了一个功能,可以让用户在使用的时候指定要不要走主库进行读取。在读取前使用下面的方式进行设置就可以了:
@GetMapping("/list")
public Object list() {
// 强制路由主库
HintManager.getInstance().setMasterRouteOnly();
return userService.list();
}
查看主库配置的sql日志,会看到打印如下,说明读操作强制走的主库:
SELECT id,name FROM t_user
●史上最强Tomcat8性能优化
●阿里巴巴为什么能抗住90秒100亿?--服务端高并发分布式架构演进之路
●B2B电商平台--ChinaPay银联电子支付功能
●学会Zookeeper分布式锁,让面试官对你刮目相看
●SpringCloud电商秒杀微服务-Redisson分布式锁方案
查看更多好文,进入公众号--撩我--往期精彩
一只 有深度 有灵魂 的公众号0.0