1. 概述
老话说的好:选择比努力更重要,如果选错了道路,就很难成功。
言归正传,之前我们聊了使用 MyCat 实现Mysql的分库分表和读写分离,MyCat是服务端的代理,使用MyCat的好处显而易见,整个分库分表和读写分离过程对Java程序来说是完全透明的,Java程序像连接Mysql一样,去连接MyCat即可。
但MyCat的运维成本较高,需要有专门的运维人员去维护,所以今天我们来聊聊另一个实现Mysql分库分表、读写分离的方案 —— ShardingSphere-JDBC。
ShardingSphere-JDBC 是一个轻量级的Java框架, 是客户端代理,不需要MyCat的中间代理,使用Java程序可以通过配置直接去实现Mysql分库分表和读写分离,适用于运维资源比较少的情况。
ShardingSphere-JDBC 支持同一库内的分表,MyCat 是不支持的,MyCat 只能在不同库内分表。
ShardingSphere-JDBC 不支持主库双写或多写,只支持一主多从的读写分离配置,因此 Mysql 集群的高可用需要使用其他手段来实现,例如 MHA。
2. 场景介绍
分片1:
服务器A IP:192.168.1.22 (Mysql从1)
服务器B IP:192.168.1.12 (Mysql主1)
服务器C IP:192.168.1.15 (Mysql主2)
服务器D IP:192.168.1.16 (Mysql从2)
分片2:
服务器E IP:192.168.1.11 (单点)
之前我们在前4台服务器上搭建了Mysql双主双从的高可用集群,该集群与服务器E实现了分表分库,本节我们使用ShardingSphere-JDBC去整合这个集群。
关于Mysql双主双从集群的具体搭建可参考以下文章:
《MyCat的快速搭建》(https://www.cnblogs.com/w84422/p/15394662.html)
《Mysql读写分离集群的搭建且与MyCat进行整合》(https://www.cnblogs.com/w84422/p/15401259.html)
《Mysql双主双从高可用集群的搭建且与MyCat进行整合》(https://www.cnblogs.com/w84422/p/15418403.html)
由于 ShardingSphere-JDBC 不支持主库双写或多写,因此我们把 服务器C 也当做一个从库来配置。
3. ShardingSphere-JDBC在Springboot中的具体使用
3.1 官网地址
https://shardingsphere.apache.org/index_zh.html
https://shardingsphere.apache.org/document/current/cn/overview/
3.2 引入依赖
这里我们使用最新的 5.0.0-beta 版本
<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.0.0-beta</version> </dependency>
3.3 配置JPA相关配置
# jpa 配置 spring.data.jpa.repositories.bootstrap-mode=default spring.data.jpa.repositories.enabled=true spring.jpa.database=mysql spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update # 启用懒加载 spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
这里要特别注意,使用ShardingSphere-JDBC + JPA 一定要启动懒加载配置,否则 getById 时会报错。
3.4 配置数据源
这里我们按照场景介绍中描述的,配置5台服务器的信息
# 配置真实数据源 spring.shardingsphere.datasource.names=master0,master1,slave0,slave1,ds1 # 配置 服务器A 数据源 spring.shardingsphere.datasource.slave0.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.slave0.jdbc-url=jdbc:mysql://192.168.1.22:3306/mycat spring.shardingsphere.datasource.slave0.username=zhuifengren spring.shardingsphere.datasource.slave0.password=Zhuifengren@123456 # 配置 服务器B 数据源 spring.shardingsphere.datasource.master0.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.master0.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.master0.jdbc-url=jdbc:mysql://192.168.1.12:3306/mycat spring.shardingsphere.datasource.master0.username=zhuifengren spring.shardingsphere.datasource.master0.password=Zhuifengren@123456 # 配置 服务器C 数据源 spring.shardingsphere.datasource.master1.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.master1.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.master1.jdbc-url=jdbc:mysql://192.168.1.15:3306/mycat spring.shardingsphere.datasource.master1.username=zhuifengren spring.shardingsphere.datasource.master1.password=Zhuifengren@123456 # 配置 服务器D 数据源 spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://192.168.1.16:3306/mycat spring.shardingsphere.datasource.slave1.username=zhuifengren spring.shardingsphere.datasource.slave1.password=Zhuifengren@123456 # 配置 服务器E 数据源 spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://192.168.1.11:3306/mycat spring.shardingsphere.datasource.ds1.username=zhuifengren spring.shardingsphere.datasource.ds1.password=Zhuifengren@123456
3.5 配置 分片1 的读写分离策略
这里我们使用轮询算法,具体的算法可参见 ShardingSphere 官网。
里面的 database-balance 是自定义的名称,与下面的负载均衡算法配置保持一致即可。
特别注意一点,ShardingSphere里面的自定义名称,一定不要包含下划线,否则会报错,虽然官网给出的示例就是包含下划线的。
# 读写分离配置 # 写数据源名称 spring.shardingsphere.rules.readwrite-splitting.data-sources.ds0.write-data-source-name=master0 # 读数据源名称,多个从数据源用逗号分隔 spring.shardingsphere.rules.readwrite-splitting.data-sources.ds0.read-data-source-names=master1,slave0,slave1 # 负载均衡算法名称 spring.shardingsphere.rules.readwrite-splitting.data-sources.ds0.load-balancer-name=database-balance # 是否启用查询一致性路由 spring.shardingsphere.rules.readwrite-splitting.data-sources.ds0.query-consistent=false # 负载均衡算法配置 # 负载均衡算法类型,这里配置为轮询 spring.shardingsphere.rules.readwrite-splitting.load-balancers.database-balance.type=ROUND_ROBIN
3.6 配置 user 表的分库分表规则
之前MyCat中我们使用的是 MyCat 默认的 auto-sharding-long 算法,user 表的 id 为 0 到 5000000 时保存在第一个分片,大于5000000保存在第二个分片,这里我们还使用这个算法。
当然也可以使用其他算法,例如 取模,大家可参见ShardingSphere的官网文档自行配置。
# 配置 user 表规则 spring.shardingsphere.rules.sharding.tables.user.actual-data-nodes=ds$->{[0,1]}.user # 配置分库策略 spring.shardingsphere.rules.sharding.tables.user.database-strategy.standard.sharding-column=id spring.shardingsphere.rules.sharding.tables.user.database-strategy.standard.sharding-algorithm-name=database-inline # 配置分表策略 spring.shardingsphere.rules.sharding.tables.user.table-strategy.standard.sharding-column=id spring.shardingsphere.rules.sharding.tables.user.table-strategy.standard.sharding-algorithm-name=table-inline spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds$->{(id <= 5000000)?0:1} spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.type=INLINE spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.props.algorithm-expression=user
3.7 JPA相关代码
User实体类:
@Entity @Table(name="user") @Setter @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class User { @Id private Integer id; private String name; @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
User数据访问类:
public interface UserRepository extends JpaRepository<User, Integer> { }
3.8 验证
这里使用JPA操作增、删、改、查操作是没有任何问题的,数据落库的分片也正确。
3.9 不得不说的几个坑
1)配置ShardingSphere-JDBC时,自定义的名称不要包含下划线,包含了会报错, 本人当时是跟了半天的源码才解决。
正确的命名:database-inline、table-inline、database-balance
错误的命名:database_inline、table_inline、database_balance
2)使用JPA需要开启懒加载,否则会报错。
3)不支持主库双写或多写,需要用其他手段保证集群的高可用。
4)官网文档写的不是很详细,很多细节需要自己摸索,例如 分片表达式 和 分片策略 的配置都没有给出示例。相对来说MyCat的官网文档就详细很多。
4. 综述
今天聊了一下 使用ShardingSphere-JDBC完成Mysql的分库分表和读写分离,希望可以对大家的工作有所帮助。
大家可以根据自己的喜好去选择使用 MyCat 或是 ShardingSphere-JDBC。
欢迎帮忙点赞、评论、转发、加关注 :)
关注追风人聊Java,每天更新Java干货。
5. 个人公众号
追风人聊Java,欢迎大家关注