背景说明
我们的Java项目已经运行了快2年了,这两年期间经过2个外包团队的开发,加上前期并没有做什么质量管理,所以代码质量比较差。项目中使用的数据库是MySQL,留着流量的增长,目前这个阶段需要着手读写分离和分表的一些事项。因为之前没有什么相关的经验,所以找了一圈使用业内比较流行的shardingsphere 中间件。
什么是 ShardingSphere
Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。
Apache ShardingSphere 设计哲学为 Database Plus,旨在构建异构数据库上层的标准和生态。 它关注如何充分合理地利用数据库的计算和存储能力,而并非实现一个全新的数据库。 它站在数据库的上层视角,关注它们之间的协作多于数据库自身。
具体介绍:shardingsphere 文档
ShardingSphere-JDBC
ShardingSphere-JDBC 定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。
ShardingSphere-JDBC 集成
ShardingSphere-JDBC 集成在代码是比较简单的,只需2个步骤:
- 引入 Maven 依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core</artifactId>
<version>${shardingsphere.version}</version>
</dependency>
- 配置 Spring Boot
# 配置 DataSource Driver
spring.datasource.driver-class-name=org.apache.shardingsphere.driver.ShardingSphereDriver
# 指定 YAML 配置文件
spring.datasource.url=jdbc:shardingsphere:classpath:xxx.yaml
注意:上面的配置版本需要是5.3.0 以上(从5.3.0开始弃用对 spring.factories
的支持),对使用5.3.0以下的用户Maven 引用就不同了,具体看对应版本的文档,像5.2.x 和5.1.x的yaml的配置也是有点不同,所以5.1.x升级到5.2.x还是要看文档。
ShardingSphere-JDBC 在项目使用的情况
在我们项目中使用遇到几个问题后,由于项目中代码比较多,改动量较大,所以我们根本不敢用到生产,以下是需要改动的地方。
- 我们继承mybatis-plus工具,很多批量保存都是用batchSave(X x),保存后无法返回自增的Id,有些业务保存后需要返回的id。(sharding-proxy 不存在这个问题)
- 不支持查询视图,这个不知道是不是我有没有记错。
还有一些问题,时间有点长了,一些问题也就忘记了。
ShardingSphere-Proxy 使用
为什么没有打算使用mycat2 ,主要是mycat2 的文档太山寨了, ShardingSphere-Proxy文档多好呀。
ShardingSphere-Proxy 定位为透明化的数据库代理端,通过实现数据库二进制协议,对异构语言提供支持。
ShardingSphere-Proxy 部署
- dockercompose 文件
version: '3.1'
services:
zoo1:
container_name: zoo1
image: zookeeper
hostname: zoo1
ports:
- 2181:2181
restart: always
volumes:
- /data/zookeeper/zoo1/data:/data
- /data/zookeeper/zoo1/conf/zoo.cfg:/conf/zoo.cfg
- /data/zookeeper/zoo1/logs:/datalog
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
ALLOW_ANONYMOUS_LOGIN: "yes"
zoo2:
container_name: zoo2
image: zookeeper
hostname: zoo2
ports:
- 2182:2181
volumes:
- /data/zookeeper/zoo2/data:/data
- /data/zookeeper/zoo2/conf/zoo.cfg:/conf/zoo.cfg
- /data/zookeeper/zoo2/logs:/datalog
restart: always
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
ALLOW_ANONYMOUS_LOGIN: "yes"
zoo3:
container_name: zoo3
image: zookeeper
hostname: zoo3
ports:
- 2183:2181
volumes:
- /data/zookeeper/zoo3/data:/data
- /data/zookeeper/zoo3/conf/zoo.cfg:/conf/zoo.cfg
- /data/zookeeper/zoo3/logs:/datalog
restart: always
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
ALLOW_ANONYMOUS_LOGIN: "yes"
sharding:
container_name: sharding-proxy
image: apache/shardingsphere-proxy:5.3.2
hostname: sharding
ports:
- 3308:3308
restart: always
volumes:
- /data/shardingsphere/conf:/opt/shardingsphere-proxy/conf
- /data/shardingsphere/ext-lib:/opt/shardingsphere-proxy/ext-lib
environment:
PORT: 3308
JVM_OPTS: "-Djava.awt.headless=true"
- 运行:
sudo docker-compose up -d
部署要注意的地方是:
- 挂载的目录里的文件,最好是用docker cp sharding-proxy:/opt/shardingsphere-proxy/conf xx, 拷贝出来修改,这样子启动才不会遇到一些坑
- 使用mysql 需要自己下载到ext-lib
以上2点官方文档有写。
ShardingSphere-Proxy 在项目使用的情况
现在说下我们在项目中使用遇到了一些问题,导致我们最后还是弃用了。
- 跨库查询:支持跨库,但是不能指定目标库,而是在数据源配置的时候,把目标库配置在一起,查询的时候直接查表就可以了,但是两个库表名刚好相同的话,我不清楚会不会报错(因为我们使用的项目中刚好没有相同表),但是要大量修改脚本。 例如:
-- 原SQL
select * from abc.table_a
-- 需要修改成
select * from table_a
- 脚本空格问题:因为我们项目比较复杂,之前没有做质量管理,所以有些sql 存在空格,胡导致查询失败,当然我们项目修改这个问题,我觉得没有什么问题。
-- 无法查询
select a. * from table
- mysql 关键字问题处理:mysql 关键字例如:
function
mybaits 的实体中 @TableField("function") 或者sql 中没有加反单引号会报错 ,需要修改成:@TableField("`function`") ,这样子需要排查所有关键字问题。 - 在事务中不支持多语句查询,例如:
-- 没有事务查询正常
SET SESSION group_concat_max_len = 102400;
select * from ...
-- 在事务中查询不出来事务中的数据
总结
Apache ShardingSphere 是一款很好的中间件,其实我还是很喜欢的,但是如果使用他需要造成项目中的大量的修改,我还是不得不放弃。
我们常常会评审一些项目是否具备读写分离和分库分表的能力,如果有项目可以加分,如果做作为要售卖的JAVA项目产品,而且有一定的数据规模,可以考虑趁早集成,这样子可以规避很多问题。