目录
一、什么是ShardingSphere
ShardingSphere是京东开源目前交给Apache的一个专门解决分库分表和读写分离等问题的框架,它是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。Apache ShardingSphere 设计哲学为 Database Plus,旨在构建异构数据库上层的标准和生态。 它关注如何充分合理地利用数据库的计算和存储能力,而并非实现一个全新的数据库。 它站在数据库的上层视角,关注它们之间的协作多于数据库自身。目前ShardingSphere包含ShardingSphere-JDBC和ShardingSphere-proxy两种解决方式。
ShardingSphere-JDBC:这是一款轻量型的框架,是对jdbc的封装,可以更轻量化的解决相关问题。只需要引入相关的依赖,配置一下yml文件或者通过java代码的方式配置就可以直接使用。
ShardingSphere-proxy:这个是需要单独部署,类似于mycat,它的定位为透明化的数据库代理,理论上支持任何使用 MySQL、PostgreSQL、openGauss 协议的客户端操作数据,对异构语言、运维场景更友好。
我今天着重的讲解一下关于ShardingSphere-JDBC的相关使用。
二、ShardingSphere-JDBC 相关功能
目前只介绍一部分最主要的功能
2.1 数据分片
传统的将数据集中存储至单一节点的解决方案,在性能、可用性和运维成本这三方面已经难于满足海量数据的场景。从性能方面来说,由于关系型数据库大多采用 B+ 树类型的索引,在数据量超过阈值的情况下,索引深度的增加也将使得磁盘访问的 IO 次数增加,进而导致查询性能的下降; 同时,高并发访问请求也使得集中式数据库成为系统的最大瓶颈。
2.1.1 垂直分片
按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。 在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将压力分散至不同的数据库。 下图展示了根据业务需要,将用户表和订单表垂直分片到不同的数据库的方案。这么做可以从一定程度上缓解单一数据库的压力,但是如果单张表的数据过大的时候,还是解决不了根本问题,会导致查询性能下降。所以在这种场景之下我们需要进行水平分片。
2.1.2 水平分片
如上所述,当单张表的数据过大的时候,如果只进行垂直拆分的话,解决不了根本性的问题,所以我们需要对单张表进行水平拆分,比如现在有一张test表,里面有1亿条数据,如果我们对这张表进行水平分片的话,我们需要建test0,test1....等等几张表,然后将这1亿条数据平均分布到这几张表中,水平分片从理论上突破了单机数据量处理的瓶颈,并且扩展相对自由,是数据分片的标准解决方案。而shardingSphere会使用逻辑表关联到数据库实际的存在的表帮我们处理数据的集合,比如分页查询、排序、筛选等。
2.2 读写分离
在解决单个数据库压力过大问题的时候,还有另外的一个优化方法,读写分离。那么为什么需要读写分离呢?面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。 对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库和从库,主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。通过一主多从的配置方式,可以将查询请求均匀的分散到多个数据副本,能够进一步的提升系统的处理能力。 使用多主多从的方式,不但能够提升系统的吞吐量,还能够提升系统的可用性,可以达到在任何一个数据库宕机,甚至磁盘物理损坏的情况下仍然不影响系统的正常运行。
2.3 广播表
如上所述,当一张表的数据量过大的时候,我们会考虑,分不同的数据库,水平分片来减轻单台数据库的压力,来达到优化的效果,但是在我们的实际场景中,不可能所有的表都有这么多的数据,比如一些配置表,那么当有这些表的时候我们该怎么办呢。shardingShere给我们提供了广播表的特性,比如我们现在有两个数据库,database0,database1,按道理来说,两个数据库里面都有这张表,这时候我们往config表中插入一条数据,那么database0,database1两个库中的config表都会有这条数据。
三、环境准备
在我们使用shardingSphere之前,我们需要先准备环境,因为shardingSphere是不会做主从同步的事情的,所以我们在使用之前需要先有一个mysql主从数据库(目前支持postgres和mysql)。在mac上安装的具体教程可以参考:【MySQL主从复制】2-Mac环境下实现MySQL主从复制_mac 搭建mysql 主从复制_风暴计划的博客-CSDN博客
四、配置和使用
4.1 引入依赖
implementation 'org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:4.1.1'
4.2 配置相关的yml
server:
port: 8080
spring:
shardingsphere:
datasource:
names: write-master0,read-master0-slave1,read-master0-slave2,write-master1,read-master1-slave1,read-master1-slave2
write-master0:
jdbc-url: jdbc:mysql://localhost:3306/CopyMasterSlave?characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Hongkong&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
username: admin
password: 123456
read-master0-slave1:
jdbc-url: jdbc:mysql://localhost:3316/CopyMasterSlave?characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Hongkong&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
username: admin
password: 123456
read-master0-slave2:
jdbc-url: jdbc:mysql://localhost:3326/CopyMasterSlave?characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Hongkong&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
username: admin
password: 123456
write-master1:
jdbc-url: jdbc:mysql://localhost:3306/CopyMasterSlave1?characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Hongkong&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
username: admin
password: 123456
read-master1-slave1:
jdbc-url: jdbc:mysql://localhost:3316/CopyMasterSlave1?characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Hongkong&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
username: admin
password: 123456
read-master1-slave2:
jdbc-url: jdbc:mysql://localhost:3326/CopyMasterSlave1?characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Hongkong&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
username: admin
password: 123456
sharding:
#读写分离相关的配置
master-slave-rules:
ds_0:
master-data-source-name: write-master0
slave-data-source-names:
- read-master0-slave1
- read-master0-slave2
load-balance-algorithm-type: ROUND_ROBIN
ds_1:
master-data-source-name: write-master1
slave-data-source-names:
- read-master1-slave1
- read-master1-slave2
load-balance-algorithm-type: ROUND_ROBIN
#分库策略
default-database-strategy:
inline:
sharding-column: id
algorithm-expression: ds_$->{id % 2}
#分表策略
binding-tables: student
tables:
student:
actual-data-nodes: ds_$->{0..1}.student$->{0..1}
table-strategy:
standard:
sharding-column: id
precise-algorithm-class-name: com.thoughtworks.shardingspheredemo.algorithm.StudentIdShardingAlgorithm
key-generator:
column: id
type: SNOWFLAKE
props:
worker:
id: 123
province:
key-generator:
column: id
type: SNOWFLAKE
props:
worker:
id: 1
class:
actual-data-nodes: ds_$->{0..1}.class
table-strategy:
inline:
sharding-column: id
algorithm-expression: class
key-generator:
column: id
type: SNOWFLAKE
props:
worker:
id: 1
#配置广播表
broadcast-tables: province
props:
sql.show: true
executor.size: 2
mybatis-plus:
mapper-locations: classpath:/mapper/*Mapper.xml
global-config:
banner: false
db-config:
id-type: auto
insert_strategy: NOT_NULL
table-underline: true
logic-delete-value: 1
logic-not-delete-value: 0
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
cache-enabled: false
local-cache-scope: statement
4.3 student表分片策略
public class StudentIdShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
return shardingValue.getLogicTableName()+new Random().nextInt(2);
}
}
4.4 实体类配置
@Data
/*
student 是shardingSphere逻辑表名
*/
@TableName("student")
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Student {
@TableId
private Long id;
private String name;
private String gender;
private Long age;
private Long classId;
}
就这几步简单配置之后就可以正常使用了
五、总结
ShardingSphere很好的帮我们解决了分库分表带来的问题,比如需要手动配置多数据源,需要处理不同数据库,表之间的分页、排序等相关问题,当然也有其他的框架也可以解决这个问题,比如mycat,但是ShardingSphere比mycat功能更加齐全,然后ShardingSphere-jdbc也不需要单独部署,使用起来更加方便,轻量!