文章目录
- [1 前言](#1 前言)
- [2 分库分表](#2 分库分表)
-
- [2.1 什么是分库分表](#2.1 什么是分库分表)
- [2.2 垂直分库](#2.2 垂直分库)
- [2.3 水平分表](#2.3 水平分表)
- [3 如何集成使用分库分表](#3 如何集成使用分库分表)
-
- [3.1 添加maven依赖](#3.1 添加maven依赖)
- [3.2 添加 shardingSphere 数据源](#3.2 添加 shardingSphere 数据源)
- [3.2 添加 sharding jdbc 配置](#3.2 添加 sharding jdbc 配置)
-
- [3.2.1 分表配置示例](#3.2.1 分表配置示例)
- [3.2.2 分库且分表配置示例](#3.2.2 分库且分表配置示例)
1 前言
为什么使用分库分表?随着业务量的增加,单表的数据量非常庞大,查询性能会变得非常差,速度非常慢,分库分表可以很友好的解决这个问题。
数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,由于无法进行分布式式部署,而一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。
2 分库分表
分库分表的目的是为了解决单表数据量过大的问题,将数据分散到不同的库的不同的表中,从而提高查询效率。当然啦,分库还可以很好的配合读写分离使用,进一步提高系统的性能。
2.1 什么是分库分表
分库分表,就是把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。根据目前社区活跃度,本项目采用
shardingsphere-jdbc 进行分库分表,可以很好的兼容SpringBoot。
使用的组件版本: shardingsphere-jdbc使用的是5.2.1
版本,动态数据源使用的是4.2.0
版本
- ShardingSphere
JDBC(前身称为Sharding-JDBC)并不是包含多个独立组件,而是一个统一的数据库访问层解决方案的组成部分。它是一个轻量级的Java框架,通过提供一套完整的JDBC驱动的方式来透明化分库分表操作,使得用户能够像操作单个数据库一样操作分布式的数据库集群。 - Sharding-JDBC:最初是指的一个专注于在Java应用中进行数据库分片(sharding)的轻量级框架,通过JDBC驱动扩展的方式实现在应用端的数据库水平扩展能力。
ShardingSphere JDBC:随着项目发展,该项目被纳入到了更广泛的Apache ShardingSphere项目之下,并正式更名为"ShardingSphere
JDBC",其不仅保留了原有的数据库分片功能,还可能增加了更多如分布式事务、数据治理等企业级特性,成为了Apache
ShardingSphere项目中针对Java应用环境下的一个模块。
所以,现在大家所说的"ShardingSphere JDBC"就是以前"Sharding-JDBC"的延续和发展,具备更强大的功能和更完善的设计。
2.2 垂直分库
垂直分库是指将表中的数据按照一定的规则,将数据分散到不同的库中,通常是按照业务功能划分到不同的数据库中,比如,将用户数据、订单数据、商品数据分别存储到不同的数据库中。
2.3 水平分表
水平分表是指将表中的数据按照一定的规则,将数据分散到表结构相同的,数据量相似的不同的表中。
3 如何集成使用分库分表
3.1 添加maven依赖
在需要使用分库分表的项目中,添加如下依赖:
xml
<parent>
<groupId>cn.smilehappiness</groupId>
<artifactId>smilehappiness-framework-base</artifactId>
<version>3.0.3-RELEASE</version>
</parent>
xml
<dependency>
<groupId>cn.smilehappiness</groupId>
<artifactId>smilehappiness-shardingjdbc</artifactId>
</dependency>
3.2 添加 shardingSphere 数据源
为需要使用分库分表的mapper类打上 @DS("shardingSphere") 注解添加指定数据源,示例如下:
java
@DS("shardingSphere")
@Repository
public interface TShardingTestModeMapper extends BaseMapper<TShardingTestMod> {
}
3.2 添加 sharding jdbc 配置
注:查询分表的数据时,需要包含分表的分片键,比如使用biz_id分表,查询数据时,where条件中,需要包含biz_id这个字段,否则将会查询所有的表数据。
3.2.1 分表配置示例
yml
spring:
#feign to configure
cloud:
openfeign:
# 默认Feign使用的是JDK自带的URLConnection进行Http,如果需要使用okhttp client,开启enabled为true
okhttp:
enabled: true
shardingsphere:
mode:
type: Standalone
props:
sql-show: true
datasource:
common:
driver-class-name: com.mysql.cj.jdbc.Driver
names: credit
credit:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://ip:port/xxx?characterEncoding=utf8&connectTimeout=10000&socketTimeout=30000&autoReconnect=true&useUnicode=true&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: admin
password: 666
rules:
sharding:
tables:
bpm_process_data_record:
actual-data-nodes: credit.bpm_process_data_record_$->{0..19}
# 分库策略
databaseStrategy:
none:
# 分表策略
table-strategy:
standard:
sharding-column: biz_id
sharding-algorithm-name: bpm-process-data-record-inline
bpm_process_record:
actual-data-nodes: credit.bpm_process_record_$->{0..9}
table-strategy:
standard:
sharding-column: biz_id
sharding-algorithm-name: bpm-process-record-inline
sharding-algorithms:
bpm-process-data-record-inline:
type: INLINE
props:
algorithm-expression: bpm_process_data_record_$->{Long.parseLong(biz_id) % 20}
bpm-process-record-inline:
type: INLINE
props:
algorithm-expression: bpm_process_record_$->{Long.parseLong(biz_id) % 10}
3.2.2 分库且分表配置示例
yml
spring:
#feign to configure
cloud:
openfeign:
# 默认Feign使用的是JDK自带的URLConnection进行Http
okhttp:
enabled: true
shardingsphere:
mode:
type: Standalone
props:
sql-show: true
datasource:
common:
driver-class-name: com.mysql.cj.jdbc.Driver
names: db0,db1,db2
db0:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://local-mysql.xxx.com:3306/db0?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: java
password: AtOd5SYDRapIOU2O!NyjL!cMK90
db1:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://local-mysql.xxx.com:3306/db1?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: java
password: AtOd5SYDRapIOU2O!NyjL!cMK90
db2:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://local-mysql.xxx.com:3306/db2?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: java
password: AtOd5SYDRapIOU2O!NyjL!cMK90
rules:
sharding:
tables:
t_sharding_test_mod:
actual-data-nodes: db$->{0..1}.t_sharding_test_mod_$->{0..2}
database-strategy:
standard:
sharding-column: id
sharding-algorithm-name: database-inline
table-strategy:
standard:
sharding-column: user_id
sharding-algorithm-name: table-inline
t_sharding_time_range:
#如果多种时间区间组合,可以使用如下配置方式
#actual-data-nodes: db2.t_sharding_time_range_$->{2023}_$->{12},db2.t_sharding_time_range_$->{2024..2025}_$->{(1..12).collect{t ->t.toString().padLeft(2,'0')}}
actual-data-nodes: db2.t_sharding_time_range_$->{2024..2025}_$->{(1..12).collect{t ->t.toString().padLeft(2,'0')}}
table-strategy:
standard:
sharding-column: created_time
sharding-algorithm-name: time-inline
sharding-algorithms:
database-inline:
type: INLINE
props:
algorithm-expression: db$->{id % 2}
table-inline:
type: INLINE
props:
algorithm-expression: t_sharding_test_mod_$->{user_id % 3}
time-inline:
type: INTERVAL
props:
datetime-pattern: "yyyy-MM-dd HH:mm:ss"
sharding-suffix-pattern: "yyyy_MM"
datetime-lower: "2024-01-01 00:00:00"
datetime-upper: "2099-12-30 00:00:00"
datetime-interval-amount: 1
datetime-interval-unit: MONTHS