做一款自己的轻量级分库分表组件(二)
在上一篇文章中,我们介绍了开发一款自定义分库分表组件所需涵盖的核心内容。这一篇,我们将正式进入设计与实现阶段。首先要解决的问题是:这款组件应该如何在 application.yml 文件中进行配置,以及这些配置项应如何优雅地映射到 Java 配置类中,便于后续使用与扩展。
一、项目结构
在设计一个支持分库分表的组件时,合理的模块划分与配置方式尤为关键。以下是本组件的项目结构:
二、配置文件设计(application.yml)
为了支持灵活的分库分表配置,我们需要在 application.yml 中定义以下配置项。配置项主要包括:
- 主数据源名称
- 所有可用数据源的基本信息(如 URL、用户名、密码、驱动类、连接池参数等)
- 分库规则列表
- 分表规则列表
这样的配置可以确保组件具备良好的可扩展性和适配能力。以下是我们本次配置文件的设计:
sharding:
# 主数据源配置
primary: ds_1
# 数据源配置
dataSources:
ds_1:
url: jdbc:mysql://localhost:3306/db_1
username: root
password: root
driverClassName: com.mysql.cj.jdbc.Driver
# 连接池配置
connection:
initialSize: 5 # 初始连接数
minIdle: 5 # 最小空闲连接
maxActive: 20 # 最大活动连接
maxWait: 60000 # 获取连接等待超时时间
timeBetweenEvictionRunsMillis: 60000 # 空闲连接检查时间
minEvictableIdleTimeMillis: 300000 # 连接最小生存时间
validationQuery: SELECT 1 # 连接检查SQL
testWhileIdle: true # 空闲时检查连接
testOnBorrow: false # 获取连接时检查
testOnReturn: false # 归还连接时检查
ds_2:
url: jdbc:mysql://localhost:3306/db_2
# ... 其他配置同上
# 分库规则配置
dbRule:
shardingKey: userId # 分片键
dbCount: 2 # 数据库数量
strategyKey: hash # 分片策略标识
strategyClass: com.ispengya.sharding.strategy.HashShardingStrategy # 策略实现类
# 分表规则配置
tableRules:
order: # 逻辑表名
shardingKey: orderId # 分片键
tableCount: 4 # 每个库的表数量
strategyKey: hash # 分片策略标识
strategyClass: com.ispengya.sharding.strategy.HashShardingStrategy # 策略实现类
user: # 另一个表的分片规则
shardingKey: userId
tableCount: 2
strategyKey: hash
strategyClass: com.ispengya.sharding.strategy.HashShardingStrategy
三、配置文件类设计 (ShardingProperties)
为了将 YAML 配置映射到 Java 类中,我们需要创建对应的配置类。如下所示:
@Data
@ConfigurationProperties(prefix = ShardingProperties.DYNAMIC_DATASOURCE_PREFIX)
public class ShardingProperties {
// 配置前缀常量,对应 application.yml 中 sharding 开头的配置
public static final String DYNAMIC_DATASOURCE_PREFIX = "sharding";
/**
* 主数据源名称,标识哪个数据源是默认使用的
*/
private String primary;
/**
* 分表配置,key为逻辑表名,value为对应的分表规则配置
*/
private Map<String, TableShardingConfig> tableSharding;
/**
* 分库配置,包含分库数量、分库字段、分库策略等
*/
private DBShardingConfig dbSharding;
/**
* 数据源配置,key为数据源名称,value为对应的数据源配置信息
*/
private Map<String, DataSourceConfig> dataSources;
@Data
public static class DataSourceConfig {
/**
* 数据库驱动类名,例如com.mysql.cj.jdbc.Driver
*/
private String driverClassName;
/**
* 数据库连接URL
*/
private String url;
/**
* 数据库用户名
*/
private String username;
/**
* 数据库密码
*/
private String password;
/**
* 连接池相关配置
*/
private ConnectionConfig connection = new ConnectionConfig();
}
@Data
public static class TableShardingConfig {
/**
* 分表总数,表的实际物理数量
*/
private int tableCount;
/**
* 逻辑表名,用于SQL解析和路由
*/
private String logicTableName;
/**
* 分表字段,基于该字段进行分表路由
*/
private String shardingKey;
/**
* 分表策略的Key,默认hash策略
*/
private String strategyKey = "hash";
/**
* 分表策略类的全限定名,如果需要自定义分表策略,则指定该字段
*/
private String strategyClassName;
}
@Data
public static class DBShardingConfig {
/**
* 分库总数,实际数据库的数量
*/
private int dbCount;
/**
* 分库字段,基于该字段进行分库路由
*/
private String shardingKey;
/**
* 分库策略的Key,默认hash策略
*/
private String strategyKey = "hash";
/**
* 分库策略类的全限定名,如果需要自定义分库策略,则指定该字段
*/
private String strategyClassName;
}
@Data
public static class ConnectionConfig {
/**
* 连接池初始化连接数
*/
private int initialSize = 5;
/**
* 连接池最小空闲连接数
*/
private int minIdle = 5;
/**
* 连接池最大活动连接数
*/
private int maxActive = 20;
/**
* 连接池获取连接最大等待时间,单位毫秒
*/
private int maxWait = 60000;
/**
* 用于检测连接是否有效的SQL语句
*/
private String validationQuery = "SELECT 1";
/**
* 是否在空闲时检测连接有效性
*/
private boolean testWhileIdle = true;
/**
* 是否在获取连接时检测有效性
*/
private boolean testOnBorrow = true;
/**
* 是否在归还连接时检测有效性
*/
private boolean testOnReturn = false;
/**
* 检测连接的周期,单位毫秒
*/
private int timeBetweenEvictionRunsMillis = 60000;
/**
* 连接在池中保持空闲而不被驱逐的最小时间,单位毫秒
*/
private int minEvictableIdleTimeMillis = 300000;
}
}
源码地址
https://github.com/ispengya/sharding