前言
上一篇中,我们介绍了主从复制,相信学过的小伙伴已经能够很好的掌握主从复制的技术,实际上也并没有那么难,虽然没有讲一主多从,多主多从的配置,但是从一主一从的配置中也很容易联想到该怎么配置,你没猜错,就是你想的那样。这篇博客,我们要讲解的东西是主从复制的应用——读写分离。一般来说,主从复制服务的对象就是读写分离,甚至于分库分表,否则完全没这个必要,今天,我们就来学习读写分离的实战应用。
ShardingJDBC
什么是ShardingJDBC
Sharding-JDBC定位为轻量级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
为什么要说ShardingJDBC呢?不是讲读写分离吗?是的,就是因为要读写分离,所以会引入多个数据源,而在我们SSM框架下,我们最多也就是引入一个datasource,所以我们只好放弃原来的配置,使用ShardingJDBC来解决多数据源的情况。
上面写的也只是其一,还有另一个重要的原因,数据在被操作的时候会有行锁,甚至表锁,如果这时候去访问这些被锁定的数据,你想想会怎么样?所以为了更好的进行读写操作,我们需要将读和写分开,这样就减轻了服务器压力,提高了服务器的利用率,同时还避免了这种情况,使得整个系统的查询性能得到极大的改善。
读写分离实战
项目准备
首先我们需要一个项目,你可以选择自己创建,但博主这里就不一步步来做了,直接使用前几日准备好的项目:Java开发 - SpringCache初体验
你也可以直接在自己已有的项目中集成,但首先需要配置好主从数据库,可参照这篇博客配置:Java开发 - MySQL主从复制初体验
以上都准备好了,那么我们就进入到下一个环节。
添加依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
添加配置
spring:
main:
allow-bean-definition-overriding: true
shardingsphere:
datasource:
names:
master,slave
# 主数据源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://172.17.0.2:3306/master_slave?characterEncoding=utf-8
username: root
password: 0
# 从数据源
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://172.17.0.4:3309/master_slave?characterEncoding=utf-8
username: root
password: 0
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
里面的注释写的很详细,基本能看明白是啥,有两个东西,这里要着重说明下:
props:
sql:
show: true #开启SQL显示,默认false
开启SQL显示博主曾在Java开发 - 拦截器初体验
中专门讲解过怎么通过拦截器输出SQL,但是看到没,这里有更简便的方式,但并不是说拦截器无用,拦截器的作用有很多,这只是其中一个。
spring:
main:
allow-bean-definition-overriding: true
如果不配置该项,项目启动之后将会报错:
报错信息表明,在声明 org.apache.shardingsphere.shardingjdbc.spring.boot 包下的SpringBootConfiguration中的dataSource这个bean时出错, 原因是有一个同名的 dataSource 的bean在com.alibaba.druid.spring.boot.autoconfigure包下的DruidDataSourceAutoConfigure类加载时已经声明了。
添加了此配置,当前项目中存在同名的bean,后定义的bean会覆盖先定义的。 而我们需要用到的是 shardingjdbc包下的dataSource,所以我们需要配置上述属性,让后加载的覆盖先加载的。
测试
一不小心,竟然快要写完了?其实博主已经说过,最重要的是配置,实际用的时候,代码不需要任何的变化,下面我们运行项目:
然后我们发现这个IP完全无法访问,这是因为这个IP是docker内部id,博主查了很多资料,都没有很好的解决这个问题,但是,也看到了一些说法:
根据这篇博客,最终得到的结论就是,虽然无法直接访问docker内部ip,但是我们已经通过端口映射到了localhost的端口上,所以,可以把docker内部ip地址换成主机地址,也可以直接用localhost,port使用映射的端口就可以。
重新启动项目,没有再报出错误,我们使用mysql工具链接时也这么做,发现完全没有问题。
还有另一篇博客:
解决docker宿主机不能访问容器的问题_docker宿主机访问不到容器
这篇博客提出在创建容器的时候,容器与宿主机共享同一个网卡,不过博主没办法重新创建容器了,有兴趣的小伙伴自行尝试。
下面通过postman来访问项目的接口地址添加用户:
报错了,我们看看控制台输出:
原来是我们前几篇博客里讲到的公共字段自动填充的锅,加了两个参数:create_time,update_time,为了能正常请求,我们在表里添加这两个字段:
alter table user add create_time DATETIME; alter table user add update_time DATETIME;
主库已经有这两个字段了,我们看下从库 :
又验证了主从的实现是完全没问题的。下面重新用postman发起添加用户的请求:
添加成功,看下控制台输出和主库:
再看下从库:
可以从控制台看出,写操作是主库,主从数据库数据都添加进去了,下面我们来做查询操作,查询新添加的用户libai:
查询成功,看下控制台输出,因为此项目使用了Redis+SpringCache,所以不会查数据库,又是自己坑自己,我们清空下Redis缓存:
然后再次查询:
可以看到,查询的数据库是从数据库,到此,读写分离 测试完成。
结语
整个过程中出现了各种各样的问题,还有一些问题在博主的步骤中没有出现,但整体上流程都是没问题的,大家在自己做的时候细心点即可,差之毫厘,谬之千里啊!读写分离介绍完了,你学的怎么样呢?有没有学废?觉得不错就给博主点个赞吧!
标签:初体验,Java,数据源,读写,JDBC,master,添加,数据库 From: https://blog.51cto.com/u_15993027/6215378