随着数据库的读写压力增大及数据量的增加,出现了数据库中间件进行分库分表的场景,现对sharding数据库中间件进行分库分表的实现进行尝试。
分库?单个数据库》多个数据库
分表?单个表》多个表
数据的切分(Sharding)分为水平分库(将数据按某种条件分开存储)和垂直分库(将数据按不同表分开存储)。
maven核心依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/sharding-jdbc-spring-boot-starter -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
核心配置
分库场景
server:
port: 9002
spring:
application:
# 分库
name: sharding-db
# 数据源名称,多数据源以逗号分隔
shardingsphere:
datasource:
names: ds0,ds1
# 数据源ds0
ds0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/write
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源ds1
ds1:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/read1
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
props:
sql.show: true
# 数据分表规则,指定所需分的表
sharding:
tables:
student: # student表
key-generator-column-name: id # 主键
database-strategy: #分库策略
inline: #行表达式
sharding-column: num #列名称,多个列以逗号分隔
algorithm-expression: ds$->{num % 2} #按模运算分配
# mybatis,放在resource目录 classpath:/mapper/*.xml
mybatis:
mapper-locations: classpath:mapper/*.xml
分表场景
server:
port: 9002
spring:
application:
# 分表
name: sharding-table
# 数据源名称,多数据源以逗号分隔
shardingsphere:
datasource:
names: ds0
# 数据源ds0
ds0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/write
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
props:
sql.show: true
# 数据分表规则,指定所需分的表
sharding:
tables:
student: # student表
key-generator-column-name: id # 主键
actual-data-nodes: ds0.student$->{0..1} # 数据节点,均匀分布
table-strategy: # 分表策略
inline: # 行表达式
shardingColumn: num # num为学号字段
algorithmExpression: student$->{num % 2} # 按模运算分配
# mybatis,放在resource目录 classpath:/mapper/*.xml
mybatis:
mapper-locations: classpath:mapper/*.xml
分库分表场景
server:
port: 9002
spring:
application:
# 分库分表
name: sharding-db-table
# 数据源名称,多数据源以逗号分隔
shardingsphere:
datasource:
names: ds0,ds1
# 数据源ds0
ds0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/write
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源ds1
ds1:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/read1
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
props:
sql.show: true
# 数据分表规则,指定所需分的表
sharding:
tables:
student: # student表
key-generator-column-name: id # 主键
actual-data-nodes: ds$->{0..1}.student$->{0..1} #数据节点,均匀分布
database-strategy: #分库策略
inline: #行表达式
sharding-column: num #列名称,多个列以逗号分隔
algorithm-expression: ds$->{num % 2} #按模运算分配
table-strategy: # 分表策略
inline: # 行表达式
sharding-column: num # no为学号字段
algorithm-expression: student$->{num % 2} # 按模运算分配
# mybatis,放在resource目录 classpath:/mapper/*.xml
mybatis:
mapper-locations: classpath:mapper/*.xml
读写分离+分表
server:
port: 9002
spring:
application:
# 读写分离+分表
name: sharding-masterslave-table
# 数据源名称,多数据源以逗号分隔
shardingsphere:
datasource:
names: ds0,ds1
# 数据源ds0
ds0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/write
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源ds1
ds1:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/read1
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
props:
sql.show: true
# 数据分表规则,指定所需分的表
sharding:
tables:
student: # student表
key-generator-column-name: id # 主键
actual-data-nodes: masterslave.student$->{0..1} #数据节点,均匀分布
table-strategy: # 分表策略
inline: # 行表达式
sharding-column: num # no为学号字段
algorithm-expression: student$->{num % 2} # 按模运算分配
master-slave-rules:
masterslave:
master-data-source-name: ds0
slave-data-source-names: ds1
# mybatis,放在resource目录 classpath:/mapper/*.xml
mybatis:
mapper-locations: classpath:mapper/*.xml
分库分表各种场景可自行验证,常规的业务操作即可。
- 在垂直方向(即业务方向)分库分表更简单
- 在水平方向(即数据方向)上,分库和分表的作用,其实是有区别的,不能混为一谈。
分库:是为了解决数据库连接资源不足问题,和磁盘IO的性能瓶颈问题。
分表:是为了解决单表数据量太大,sql语句查询数据时,即使走了索引也非常耗时问题。此外还可以解决消耗cpu资源问题。
分库分表:可以解决 数据库连接资源不足、磁盘IO的性能瓶颈、检索数据耗时 和 消耗cpu资源等问题。
具体使用需根据真实的业务需求。