赞
踩
项目存储的数据量过多,所以需要对数据进行分表处理,以下只针对ShardingSphere插件的自定义配置操作
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.0</version>
</dependency>
<!--sharding 5.1.0版本依赖tamcat-dbcp 10.0.16或者以上版本-->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>10.0.16</version>
</dependency>
官方地址:
https://shardingsphere.apache.org/document/5.1.0/cn/user-manual/shardingsphere-jdbc/spring-boot-starter/
自定义配置:(使用的pgsql数据库,所有的分表都需要提前建好,建议使用定时任务处理!!!)
spring: shardingsphere: #模式配置 mode: #持久化仓库类型 type: Standalone repository: type: File overwrite: true datasource: # 真实数据源名称,多个数据源用逗号区分 names: yun # 配置第一个数据源 yun: # 使用阿里的Druid连接池 type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.postgresql.Driver url: jdbc:postgresql://127.0.0.1:3396/testSharding username: test password: test #其他数据库连接属性需要配置在datasource级别下!!! initial-size: 5 min-idle: 5 maxActive: 20 # 配置获取连接等待超时的时间 maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 # 打开PSCache,并且指定每个连接上PSCache的大小 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 filters: stat,wall,slf4j # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000 rules: sharding: #分表策略 tables: #表名 test_info_tb: #通过行表达式匹配表名 actual-data-nodes: yun.test_info_tb_$->{2023..2050}$->{['01','02','03','04','05','06','07','08','09','10','11','12']}_$->{0..19} table-strategy: complex: sharding-columns: id,create_time # 分布式序列算法名称 sharding-algorithm-name: info #分片算法配置 sharding-algorithms: # 前面自定义的分布式序列算法名称 info: #类型使用自定义类型 type: CLASS_BASED props: strategy: COMPLEX #填写全限定类名 algorithmClassName: com.message.psmessageservice.sharding.SendTbComplexKeysShardingAlgorithm
配置完成之后记得删除之前手动注入的Datasource依赖,同时在启动类下@SpringBootApplication的注解排除DruidDataSourceAutoConfigure类
/*@Bean("DataSource")
@ConfigurationProperties(prefix = "spring.datasource.yun")
public DataSource druidDataSource(){
return new DruidDataSource();
}*/
@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class})
package com.message.psmessageservice.sharding; import com.google.common.collect.Range; import com.message.psmessageservice.utils.TimeUtils; import lombok.extern.slf4j.Slf4j; import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm; import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingValue; import java.util.*; /** * @Author chenqian * @Description 自定义复合分表策略 * @Date 2023-09-19 17:10 * @Version 1.0 */ @Slf4j public class SendTbComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<String> { @Override public Collection<String> doSharding(Collection<String> databaseNames, ComplexKeysShardingValue<String> complexKeysShardingValue) { // 得到每个分片健对应的值 Collection<Object> timeValues = this.getShardingValue(complexKeysShardingValue, "create_time"); Collection<Object> idValues = this.getShardingValue(complexKeysShardingValue, "id"); List<String> shardingSuffix = new ArrayList<>(); // 对时间按月处理,对user_id取模20处理 for (Object id : idValues) { for (Object time : timeValues) { String date = TimeUtils.secondsToDateStr(Long.parseLong(time.toString()) * 1000, "yyyyMM"); int num = id.hashCode() > 0 ? id.hashCode() : -id.hashCode(); String suffix = "_" + date + "_" + num % 20; for (String databaseName : databaseNames) { if (databaseName.endsWith(suffix)) { shardingSuffix.add(databaseName); } } } } return shardingSuffix; } private Collection<Object> getShardingValue(ComplexKeysShardingValue<String> shardingValues, final String key) { Collection<Object> valueSet = new ArrayList<>(); Map<String, Collection<String>> columnNameAndShardingValuesMap = shardingValues.getColumnNameAndShardingValuesMap(); if (columnNameAndShardingValuesMap.containsKey(key)) { valueSet.addAll(columnNameAndShardingValuesMap.get(key)); } //自定义时间范围匹配表名 Map<String, Range<String>> columnNameAndRangeValuesMap = shardingValues.getColumnNameAndRangeValuesMap(); if (columnNameAndRangeValuesMap.containsKey(key)) { //时间范围默认查询半年 Long startTime = System.currentTimeMillis() / 1000 - 6 * 30 * 86400; Long endTime = System.currentTimeMillis() / 1000; Range<String> endTimeRange = columnNameAndRangeValuesMap.get(key); if (endTimeRange.hasLowerBound()) { //取值采用Object类接收,再去做转换,因为会返回数据本身的包装类型,防止报错 Object endpoint = endTimeRange.lowerEndpoint(); startTime = Long.parseLong(String.valueOf(endpoint)); } if (endTimeRange.hasUpperBound()) { Object upperBound = endTimeRange.upperEndpoint(); endTime = Long.parseLong(String.valueOf(upperBound)); } valueSet.add(startTime); valueSet.add(endTime); } return valueSet; } @Override public void init() { } @Override public String getType() { return "INFO"; } @Override public Properties getProps() { return ComplexKeysShardingAlgorithm.super.getProps(); } @Override public void setProps(Properties props) { ComplexKeysShardingAlgorithm.super.setProps(props); } }
自定义代码不生效问题:在resouces/META-INF/services目录下创建一个org.apache.shardingsphere.sharding.spi.ShardingAlgorithm的文件名,写下自定义的全限定类名去覆盖源码中的文件从而生效。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。