本文是基于上一讲SpringCloud H.SR7 + sharding-jdbc 4.1.1-水平分库分表 接下来我们继续介绍分库分表和数据广播
先上一个yml配置,对了maven的配置上上一篇是一样这里就不介绍了
server:
port: 8080
datasource0:
url: jdbc:mysql://localhost:3306/user_db?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2b8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: root
datasource1:
url: jdbc:mysql://localhost:3306/edu_db_1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2b8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: root
datasource2:
url: jdbc:mysql://localhost:3306/edu_db_2?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2b8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: root
然后开始写配置,首先是雪花算法配置类:
@Configuration
public class KeyIdConfig {
@Bean("userKeyGenerator")
public SnowflakeShardingKeyGenerator userKeyGenerator() {
return new SnowflakeShardingKeyGenerator();
}
@Bean("orderKeyGenerator")
public SnowflakeShardingKeyGenerator orderKeyGenerator() {
return new SnowflakeShardingKeyGenerator();
}
}
然后是数据源配置:
@Configuration
public class DBConf {
@Value("${datasource0.url}")
private String url0;
@Value("${datasource0.username}")
private String username0;
@Value("${datasource0.password}")
private String password0;
@Value("${datasource0.driver-class-name}")
private String driverClassName0;
@Value("${datasource1.url}")
private String url1;
@Value("${datasource1.username}")
private String username1;
@Value("${datasource1.password}")
private String password1;
@Value("${datasource1.driver-class-name}")
private String driverClassName1;
@Value("${datasource2.url}")
private String url2;
@Value("${datasource2.username}")
private String username2;
@Value("${datasource2.password}")
private String password2;
@Value("${datasource2.driver-class-name}")
private String driverClassName2;
@Bean("dataSource")
public DataSource dataSource() {
try {
// Sharding全局配置
ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
//配置t_user
shardingRuleConfiguration.getTableRuleConfigs().add(confTUserRule());
//配置Course的水平分布
shardingRuleConfiguration.getTableRuleConfigs().add(confCourseRule());
//配置公共字典表
shardingRuleConfiguration.getTableRuleConfigs().add(confTudictRule());
//配置teacher表
shardingRuleConfiguration.getTableRuleConfigs().add(confTeacherRule());
//如果添加数据则三个库都会添加,如果删除则三个库都会删除
shardingRuleConfiguration.getBroadcastTables().add("t_udict");
// 自定义算法
//shardingRuleConfiguration.setDefaultDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("t_id", "m1"));
//shardingRuleConfiguration.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("t_id", new TableShardingAlgorithm()));
// 创建数据源
Properties props=new Properties();
props.put("sql.show", "true");
DataSource dataSource = ShardingDataSourceFactory.createDataSource(confDataSourceMap(), shardingRuleConfiguration, props);
return dataSource;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
private TableRuleConfiguration confTeacherRule() {
// 配置表规则
TableRuleConfiguration teacherConf = new TableRuleConfiguration("teacher", "m$->{1..2}.teacher_$->{1..2}");
// 行表达式分表规则
teacherConf.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("t_id", new TableShardingAlgorithm()));
// 行表达式分库规则
teacherConf.setDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("t_key", new DatabaseShardingAlgorithm()));
return teacherConf;
}
/**
* 水平分库分表
* @return
*/
private TableRuleConfiguration confCourseRule() {
// 配置表规则
TableRuleConfiguration courseConfig = new TableRuleConfiguration("course", "m$->{1..2}.course_$->{1..2}");
// 行表达式分表规则
courseConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("cid", "course_$->{cid % 2 + 1}"));
// 行表达式分库规则
courseConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "m$->{user_id % 2 + 1}"));
return courseConfig;
}
/**
* 配置公共字典表(每个数据库都有一个t_udict表)
* @return
*/
private TableRuleConfiguration confTudictRule() {
TableRuleConfiguration dictConfig = new TableRuleConfiguration("t_udict");
dictConfig.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "dict_id"));
return dictConfig;
}
/**
* 配置t_user专库配置(垂直分配)
* @return
*/
private TableRuleConfiguration confTUserRule() {
// 配置表规则: t_user表在m0库中
TableRuleConfiguration userRuleConfiguration = new TableRuleConfiguration("t_user", "m$->{0}.t_user");
//配置生成策略
userRuleConfiguration.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "user_id"));
// 行表达式分表规则
userRuleConfiguration.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "t_user"));
// 行表达式分库规则,专库专表不需要下面的配置
//userRuleConfiguration.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "m$->{user_id % 2 + 1}"));
return userRuleConfiguration;
}
/**
* 配置数据源
* @return
*/
private Map<String, DataSource> confDataSourceMap() {
DruidDataSource dataSource0 = new DruidDataSource();
dataSource0.setDriverClassName(this.driverClassName0);
dataSource0.setUrl(this.url0);
dataSource0.setUsername(this.username0);
dataSource0.setPassword(this.password0);
//dataSource0.setFilters(this.filters);
DruidDataSource dataSource1 = new DruidDataSource();
dataSource1.setDriverClassName(this.driverClassName1);
dataSource1.setUrl(this.url1);
dataSource1.setUsername(this.username1);
dataSource1.setPassword(this.password1);
//dataSource1.setFilters(this.filters);
DruidDataSource dataSource2 = new DruidDataSource();
dataSource2.setDriverClassName(this.driverClassName2);
dataSource2.setUrl(this.url2);
dataSource2.setUsername(this.username2);
dataSource2.setPassword(this.password2);
//dataSource2.setFilters(this.filters);
//分库设置
Map<String, DataSource> dataSourceMap = new HashMap<>(3);
//添加两个数据库database0和database1
dataSourceMap.put("m0", dataSource0);
dataSourceMap.put("m1", dataSource1);
dataSourceMap.put("m2", dataSource2);
return dataSourceMap;
}
}
confTeacherRule()这个方法中的分片策略不是采用配置,而是自定义算法,需要提供如下两个类实现,首先是数据库的分片策略实现类:
public class DatabaseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> databaseNames, PreciseShardingValue<Long> shardingValue) {
for (String database : databaseNames) {
if (database.endsWith("2")) {
return database;
}
}
return "";
}
}
然后是表的分片策略实现类:
public class TableShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> tableNames, PreciseShardingValue<Long> shardingValue) {
for (String table : tableNames) {
if (table.endsWith(String.valueOf(shardingValue.getValue() % 2 + 1))) {
return table;
}
}
return "";
}
}
到这里关键的配置就完成了。这里跟上个小节主要的不同在于介绍了用实现类的方式来代替配置,还有就是广播,看下面的关键代码:
/**
* 配置公共字典表(每个数据库都有一个t_udict表)
* @return
*/
private TableRuleConfiguration confTudictRule() {
TableRuleConfiguration dictConfig = new TableRuleConfiguration("t_udict");
dictConfig.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "dict_id"));
return dictConfig;
}
//配置公共字典表
shardingRuleConfiguration.getTableRuleConfigs().add(confTudictRule());
//如果添加数据则三个库都会添加,如果删除则三个库都会删除
shardingRuleConfiguration.getBroadcastTables().add("t_udict");
这样一来当保存t_udict的数据时会往edu_db_1、edu_db_2、user_db三个数据库的t_udict表中插入。这里给出t_udict的sql语句,实体类代码就不给出了
CREATE TABLE `t_udict` (
`dict_id` bigint(20) NOT NULL,
`dict_status` varchar(100) DEFAULT NULL,
`dict_value` varchar(100) DEFAULT NULL,
PRIMARY KEY (`dict_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
到这里就结束完sharding-jdbc分库分表的实现,下一篇介绍读写分离。