blog

"봄"boot2.6.4 통합 샤딩-jdbc5.1

기반 및 샤딩-jdbc5.1 이 샤딩 알고리즘은 샤딩 Ken을 수행하는 시간을 기반으로 합니다. 단일 테이블의 시간 범위를 구성할 수 있습니다(예: 테이블당 3일 또는 테이블당 5...

Oct 11, 2025 · 18 min. read
シェア

서문: 이 슬라이싱 알고리즘은 슬라이싱 Jian을 수행하는 시간을 기반으로 합니다. 예를 들어 하나의 테이블을 3일 동안 또는 하나의 테이블을 5일 동안 사용하려는 경우 데이터의 양에 따라 동적으로 구성할 수 있습니다. 다음 코드 조각, 전체 코드는 깃허브의 [코드 링크]에서 확인할 수 있습니다. 코드 구조는 아래와 같습니다:

I. 종속성 추가

<dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 <version>2.6.4</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 <version>2.6.4</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
 <version>3.1.4</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-actuator</artifactId>
 <version>2.6.4</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-commons</artifactId>
 <version>3.1.5</version>
 </dependency>
 <dependency>
 <groupId>org.flywaydb</groupId>
 <artifactId>flyway-core</artifactId>
 <!-- <version>5.2.4</version>-->
 </dependency>
 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-openfeign</artifactId>
 <version>3.1.5</version>
 </dependency>
 <!-- https://.com/artifact/.alibaba/druid -->
 <dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid</artifactId>
 <version>1.2.20</version>
 </dependency>
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.18.20</version>
 </dependency>
 <!--데이터베이스 연결은 mysql로 --.>
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>8.0.22</version>
 </dependency>
 <dependency>
 <groupId>org.apache.shardingsphere</groupId>
 <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
 <version>5.1.0</version>
 </dependency>
 <!-- ShardingJDBC 5.1.0드루이드 연결 풀링을 사용하려면 dbcp 종속성을 추가해야 합니다.>
 <dependency>
 <groupId>org.apache.tomcat</groupId>
 <artifactId>tomcat-dbcp</artifactId>
 <version></version>
 </dependency>
 <!-- MyBatis-Plus -->
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-boot-starter</artifactId>
 <version>3.3.1</version>
 </dependency>
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-generator</artifactId>
 <version>3.3.1</version>
 </dependency>
 <!-- Mybatis에 대한 페이징 플러그인 --.>
 <dependency>
 <groupId>com.github.pagehelper</groupId>
 <artifactId>pagehelper-spring-boot-starter</artifactId>
 <version>1.3.0</version>
 </dependency>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.9</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-freemarker</artifactId>
 <version>2.6.4</version>
 </dependency>
</dependencies>

구성 파일 추가하기

  • 데이터베이스 측의 구성은 기본적으로 정상적으로 추가할 수 있습니다. 기본적으로 드루이드를 사용한 연결 풀링이 사용됩니다.
  • 슬라이싱 규칙과 관련된 구성입니다:
# 샤딩을 위한 실제 테이블, 물리적 테이블
spring.shardingsphere.rules.sharding.tables.t_user.actual-data-nodes=ifaas_client.t_user
# 샤딩이 수행되는 샤딩 테이블의 필드, 샤딩 수행 기준
spring.shardingsphere.rules.sharding.tables.t_user.table-strategy.standard.sharding-column=create_time
# 샤딩 알고리즘의 이름
spring.shardingsphere.rules.sharding.tables.t_user.table-strategy.standard.sharding-algorithm-name=time-sharding-algorithm
# 샤딩 테이블의 기본 키는 다음과 같습니다.,
spring.shardingsphere.rules.sharding.tables.t_user.key-generate-strategy.column=id
# 샤딩 테이블의 기본 키를 생성하는 로직으로, 기본값은 기본 키 충돌을 방지하기 위해 눈송이 알고리즘을 사용합니다.
spring.shardingsphere.rules.sharding.tables.t_user.key-generate-strategy.key-generator-name=snowflake
# 기본 유형에 따른 시간 분할 테이블의 유형
spring.shardingsphere.rules.sharding.sharding-algorithms.time-sharding-algorithm.type=CLASS_BASED
# 샤딩 테이블의 모드는 표준 모드입니다.
spring.shardingsphere.rules.sharding.sharding-algorithms.time-sharding-algorithm.props.strategy=standard
# 테이블을 샤딩하는 알고리즘의 이름으로, 샤딩 알고리즘의 클래스 이름인 TimeShardingAlgorithm에 해당하며 대문자가 없고 짧은 캐리로 연결된 험프가 있습니다.
spring.shardingsphere.rules.sharding.sharding-algorithms.time-sharding-algorithm.props.algorithmClassName=com.yuzi.sharding.TimeShardingAlgorithm
server.port=9002 spring.application.name=ifaas-file eureka.client.service-url.defaultZone = "http://...1:9725"/eureka/ eureka.instance.lease-expiration-duration-in-seconds = 65 eureka.instance.lease-renewal-interval-in-seconds = 20 eureka.client.healthcheck.enabled = true eureka.instance.prefer-ip-address = true spring.main.allow-bean-definition-overriding=true spring.main.allow-circular-references=true spring.datasource.host=jdbc:mysql://localhost:3306 spring.datasource.url = ${spring.datasource.host}/ifaas_client?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Tokyo spring.datasource.password = 123456 spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver spring.datasource.username = root spring.datasource.hikari.maximum-pool-size=30 spring.datasource.hikari.minimum-idle=10 spring.datasource.hikari.max-lifetime=2000 spring.shardingsphere.props.sql.show=true spring.shardingsphere.datasource.names=mydb spring.shardingsphere.datasource.mydb.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.mydb.url=${spring.datasource.host}/ifaas_client?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Tokyo spring.shardingsphere.datasource.mydb.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.mydb.username=root spring.shardingsphere.datasource.mydb.password=123456 spring.shardingsphere.datasource.mydb.initial-size=5 spring.shardingsphere.datasource.mydb.min-idle=5 spring.shardingsphere.datasource.mydb.max-active=20 spring.shardingsphere.datasource.mydb.max-wait=60000 spring.shardingsphere.datasource.mydb.time-between-eviction-runs-millis=60000 spring.shardingsphere.datasource.mydb.min-evictable-idle-time-millis=300000 spring.shardingsphere.datasource.mydb.validation-query=SELECT 1 FROM DUAL spring.shardingsphere.datasource.mydb.test-while-idle=true spring.shardingsphere.datasource.mydb.test-on-borrow=false spring.shardingsphere.datasource.mydb.test-on-return=false spring.shardingsphere.datasource.mydb.pool-prepared-statements=true spring.shardingsphere.datasource.mydb.max-pool-prepared-statement-per-connection-size=20 spring.shardingsphere.datasource.mydb.use-global-data-source-stat=true spring.shardingsphere.datasource.mydb.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 spring.shardingsphere.rules.sharding.tables.t_user.actual-data-nodes=ifaas_client.t_user spring.shardingsphere.rules.sharding.tables.t_user.table-strategy.standard.sharding-column=create_time spring.shardingsphere.rules.sharding.tables.t_user.table-strategy.standard.sharding-algorithm-name=time-sharding-algorithm spring.shardingsphere.rules.sharding.tables.t_user.key-generate-strategy.column=id spring.shardingsphere.rules.sharding.tables.t_user.key-generate-strategy.key-generator-name=snowflake spring.shardingsphere.rules.sharding.sharding-algorithms.time-sharding-algorithm.type=CLASS_BASED spring.shardingsphere.rules.sharding.sharding-algorithms.time-sharding-algorithm.props.strategy=standard spring.shardingsphere.rules.sharding.sharding-algorithms.time-sharding-algorithm.props.algorithmClassName=com.yuzi.sharding.TimeShardingAlgorithm mybatis-plus.mapper-locations=classpath*:mybatis/mapper/*.xml mybatis-plus.type-aliases-package.yuzi.entity mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl pagehelper.helperDialect=postgresql spring.flyway.enabled= true spring.flyway.encoding= UTF-8 spring.flyway.locations=classpath:db/migration spring.flyway.url= jdbc:mysql://localhost:3306/ifaas_client?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Tokyo spring.flyway.user= root spring.flyway.password= 123456

, 하위 테이블의 핵심 로직인 슬라이싱 알고리즘을 작성합니다.

이 샤딩 알고리즘은 샤딩 키로 시간을 사용하는 샤딩으로, 샤딩의 시간 범위가 설정에 지원되는 샤딩 알고리즘 인터페이스 표준샤딩알고리즘을 구현하는 데 필요한 타임샤딩알고리즘 클래스입니다.

@Slf4j
public class TimeShardingAlgorithm implements StandardShardingAlgorithm<LocalDateTime> {
 /**
 * 테이블 샤딩 표기법, 예: t_contract_202201 샤딩 기호가 "_"
 */
 private final String TABLE_SPLIT_SYMBOL = "_";
 /**
 * 정밀 샤딩
 * @param tableNames 해당 샤딩 라이브러리에 있는 모든 샤딩 테이블의 모음입니다.
 * @param preciseShardingValue 여기서 logicTableName은 논리적 테이블, columnName은 샤딩 키, value는 SQL에서 파싱된 샤딩 키의 값입니다.
 * @return  
 */
 @Override
 public String doSharding(Collection<String> tableNames, PreciseShardingValue<LocalDateTime> preciseShardingValue) {
 String logicTableName = preciseShardingValue.getLogicTableName();
 ShardingTableCacheEnum logicTable = ShardingTableCacheEnum.of(logicTableName);
 if (logicTable == null) {
 log.error(">>>>>>>>>> ERROR데이터 테이블 유형이 잘못되었습니다. 나중에 다시 시도하세요. 로그 테이블 이름:{},logicTableName:{}",
 ShardingTableCacheEnum.logicTableNames(), logicTableName);
 throw new IllegalArgumentException("데이터 테이블 유형 오류, 나중에 다시 시도하세요");
 }
 // 히트 샤딩 테이블 결정
 LocalDateTime dateTime = preciseShardingValue.getValue();
 String resultTableName = getActualTable(logicTable, dateTime);
 if (StringUtils.isBlank(resultTableName)){
 // 샤딩 테이블이 존재하지 않는 경우 기본 테이블을 반환합니다.
 resultTableName = logicTableName + TABLE_SPLIT_SYMBOL + "0";
 }
 // 샤딩 정보 인쇄
 log.info(">>>>>>>>>> INFO논리적 테이블을 사용한 정밀한 샤딩:{},물리적 테이블:{}", logicTableName, resultTableName);
 return resultTableName;
 }
 /**
 * 범위 슬라이싱
 * @param tableNames 해당 샤딩 라이브러리에 있는 모든 샤딩 테이블의 모음입니다.
 * @param rangeShardingValue 샤딩 범위
 * @return 테이블 이름 모음
 */
 @Override
 public Collection<String> doSharding(Collection<String> tableNames, RangeShardingValue<LocalDateTime> rangeShardingValue) {
 String logicTableName = rangeShardingValue.getLogicTableName();
 ShardingTableCacheEnum logicTable = ShardingTableCacheEnum.of(logicTableName);
 if (logicTable == null) {
 log.error(">>>>>>>>>> ERROR논리 테이블 범위 예외, 나중에 다시 시도하세요. 논리 테이블 이름:{},logicTableName:{}",
 ShardingTableCacheEnum.logicTableNames(), logicTableName);
 throw new IllegalArgumentException("논리적 테이블 범위 예외, 나중에 다시 시도하세요");
 }
 // 샤딩 테이블 범위의 주기적 계산
 Set<String> resultTableNames = getActualTableSet(logicTable,rangeShardingValue.getValueRange());
 if (CollectionUtils.isEmpty(resultTableNames)){
 // 기본 테이블이 존재하지 않는 경우 기본 테이블 반환
 resultTableNames = new HashSet<>();
 resultTableNames.add(logicTableName + TABLE_SPLIT_SYMBOL + "0");
 }
 // 샤딩 정보 인쇄
 log.info(">>>>>>>>>> INFO범위 슬라이싱, 논리적 테이블:{},물리적 테이블:{}", logicTableName, resultTableNames);
 return resultTableNames;
 }
 @Override
 public String getType() {
 return null;
 }
 @Override
 public void init() {
 }
 // --------------------------------------------------------------------------------------------------------------
 // 비공개 메서드
 // --------------------------------------------------------------------------------------------------------------
 /**
 * 최소 샤딩 값 가져오기
 * @param tableNames 테이블 이름 모음
 * @return 최소 샤딩 값
 */
 private LocalDateTime getLowerEndpoint(Collection<ShardingRecord> tableNames) {
 Optional<LocalDateTime> optional = tableNames.stream()
 .map(ShardingRecord::getStartTime)
 .min(Comparator.comparing(Function.identity()));
 if (optional.isPresent()) {
 return optional.get();
 } else {
 log.error(">>>>>>>>>> ERROR데이터 최소 샤딩 테이블을 가져오지 못했습니다. 나중에 다시 시도하세요. tableName:{}", tableNames);
 throw new IllegalArgumentException("데이터 최소 샤딩 테이블을 가져오는 데 실패했습니다. 나중에 다시 시도하세요.");
 }
 }
 /**
 * 최대 샤딩 값 가져오기
 * @param tableNames 테이블 이름 모음
 * @return 최대 샤딩 값
 */
 private LocalDateTime getUpperEndpoint(Collection<ShardingRecord> tableNames) {
 Optional<LocalDateTime> optional = tableNames.stream()
 .map(ShardingRecord::getEndTime)
 .max(Comparator.comparing(Function.identity()));
 if (optional.isPresent()) {
 return optional.get();
 } else {
 log.error(">>>>>>>>>> ERRORmaxSplitTable 데이터를 가져오지 못했습니다. 나중에 tableName을 다시 시도하세요:{}", tableNames);
 throw new IllegalArgumentException("데이터 최대 샤딩 테이블을 가져오는 데 실패했습니다. 나중에 다시 시도하세요.");
 }
 }
 private String getActualTable(ShardingTableCacheEnum logicTable, LocalDateTime dateTime) {
 AtomicReference<String> tableName = new AtomicReference<>();
 long dateTimeLong = DateUtil.localDateTimeToLong(dateTime);
 logicTable.resultTableNamesCache().forEach(shardingRecord -> {
 if (DateUtil.localDateTimeToLong(shardingRecord.getStartTime()) <= dateTimeLong &&
 DateUtil.localDateTimeToLong(shardingRecord.getEndTime()) >= dateTimeLong){
 tableName.set(shardingRecord.getActualTable());
 }
 });
 return tableName.get();
 }
 private Set<String> getActualTableSet(ShardingTableCacheEnum logicTable, Range<LocalDateTime> valueRange) {
 Set<String> tableNameList = new HashSet<>();
 // between and 시작 값은
 boolean hasLowerBound = valueRange.hasLowerBound();
 boolean hasUpperBound = valueRange.hasUpperBound();
 // 최대값 및 최소값 가져오기
 Set<ShardingRecord> tableNameCache = logicTable.resultTableNamesCache();
 LocalDateTime min = hasLowerBound ? valueRange.lowerEndpoint() :getLowerEndpoint(tableNameCache);
 LocalDateTime max = hasUpperBound ? valueRange.upperEndpoint() :getUpperEndpoint(tableNameCache);
 long minLong = DateUtil.localDateTimeToLong(min);
 long maxLong = DateUtil.localDateTimeToLong(max);
 logicTable.resultTableNamesCache().forEach(shardingRecord -> {
 long startTimeLong = DateUtil.localDateTimeToLong(shardingRecord.getStartTime());
 long endTimeLong = DateUtil.localDateTimeToLong(shardingRecord.getEndTime());
 if (!(maxLong < startTimeLong || endTimeLong < minLong)){
 //  
 tableNameList.add(shardingRecord.getActualTable());
 }
 });
 return tableNameList;
 }
}

커스텀 슬라이싱 알고리즘 툴 클래스

@Slf4j
public class ShardingAlgorithmTool {
 private static IShardingRecordService shardingRecordService;
 /** 테이블 샤딩 표기법, 예: t_user_202201 샤딩 기호가 "_" */
 private static final String TABLE_SPLIT_SYMBOL = "_";
 /** 데이터베이스 구성*/
 private static final Environment ENV = SpringUtil.getApplicationContext().getEnvironment();
 private static final String DATASOURCE_URL = ENV.getProperty("spring.shardingsphere.datasource.mydb.url");
 private static final String DATASOURCE_USERNAME = ENV.getProperty("spring.shardingsphere.datasource.mydb.username");
 private static final String DATASOURCE_PASSWORD = ENV.getProperty("spring.shardingsphere.datasource.mydb.password");
 /**
 * 샤딩 관리 서비스 초기화
 * @param service
 */
 public static void initService(IShardingRecordService service){
 shardingRecordService = service;
 }
 /**
 * 모든 캐시 다시 로드
 */
 public static void tableNameCacheReloadAll() {
 Arrays.stream(ShardingTableCacheEnum.values()).forEach(ShardingAlgorithmTool::tableNameCacheReload);
 }
 /**
 * 지정된 샤딩 캐시를 다시 로드합니다.
 * @param logicTable 논리적 테이블, 예: t_user
 */
 public static void tableNameCacheReload(ShardingTableCacheEnum logicTable) {
 // 데이터베이스의 모든 테이블 이름 읽기
 List<ShardingRecord> tableNameList = getAllTableNameBySchema(logicTable);
 // 캐시, 구성 업데이트
 logicTable.atomicUpdateCacheAndActualDataNodes(tableNameList);
 // 이전 캐시 삭제
 logicTable.resultTableNamesCache().clear();
 // 새 캐시에 쓰기
 logicTable.resultTableNamesCache().addAll(tableNameList);
 }
 /**
 * 모든 테이블 이름 가져오기
 * @return 테이블 이름 모음
 * @param logicTable  
 */
 public static List<ShardingRecord> getAllTableNameBySchema(ShardingTableCacheEnum logicTable) {
 List<ShardingRecord> tableNames = new ArrayList<>();
 try {
 String logicTableName = logicTable.logicTableName();
 tableNames = shardingRecordService.queryAllShardingRecordByLogicName(logicTableName);
 } catch (Exception e) {
 log.error(">>>>>>>>>> ERROR데이터베이스 연결에 실패했습니다. 나중에 다시 시도하세요, 이유:{}", e.getMessage(), e);
 }
 return tableNames;
 }
 /**
 * 실제 데이터 노드 구성 동적 업데이트
 *
 * @param logicTableName 논리적 테이블 이름
 * @param tableNamesCache 실제 테이블 이름 수집
 */
 public static void actualDataNodesRefresh(String logicTableName, List<ShardingRecord> tableNamesCache) {
 try {
 if (CollectionUtils.isEmpty(tableNamesCache)){
 // 테이블이 없을 때 처음에 초기화 방지
 return;
 }
 // 데이터 샤딩 노드 가져오기
 String dbName = "mydb";
 log.info(">>>>>>>>>> INFO샤딩 테이블 구성 업데이트,logicTableName:{},tableNamesCache:{}", logicTableName, tableNamesCache);
 // generate actualDataNodes
 String newActualDataNodes = tableNamesCache.stream().map(ShardingRecord::getActualTable).map(o -> String.format("%s.%s", dbName, o)).collect(Collectors.joining(","));
 ShardingSphereDataSource shardingSphereDataSource = SpringUtil.getBean(ShardingSphereDataSource.class);
 updateShardRuleActualDataNodes(shardingSphereDataSource, logicTableName, newActualDataNodes);
 }catch (Exception e){
 log.error("초기화 동적 양식 실패, 이유:{}", e.getMessage(), e);
 }
 }
 // --------------------------------------------------------------------------------------------------------------
 // 비공개 메서드
 // --------------------------------------------------------------------------------------------------------------
 /**
 * RefreshActualDataNodes
 */
 private static void updateShardRuleActualDataNodes(ShardingSphereDataSource dataSource, String logicTableName, String newActualDataNodes) {
 // Context manager.
 ContextManager contextManager = dataSource.getContextManager();
 // Rule configuration.
 String schemaName = "logic_db";
 Collection<RuleConfiguration> newRuleConfigList = new LinkedList<>();
 Collection<RuleConfiguration> oldRuleConfigList = dataSource.getContextManager()
 .getMetaDataContexts()
 .getMetaData(schemaName)
 .getRuleMetaData()
 .getConfigurations();
 for (RuleConfiguration oldRuleConfig : oldRuleConfigList) {
 if (oldRuleConfig instanceof AlgorithmProvidedShardingRuleConfiguration) {
 // Algorithm provided sharding rule configuration
 AlgorithmProvidedShardingRuleConfiguration oldAlgorithmConfig = (AlgorithmProvidedShardingRuleConfiguration) oldRuleConfig;
 AlgorithmProvidedShardingRuleConfiguration newAlgorithmConfig = new AlgorithmProvidedShardingRuleConfiguration();
 // Sharding table rule configuration Collection
 Collection<ShardingTableRuleConfiguration> newTableRuleConfigList = new LinkedList<>();
 Collection<ShardingTableRuleConfiguration> oldTableRuleConfigList = oldAlgorithmConfig.getTables();
 oldTableRuleConfigList.forEach(oldTableRuleConfig -> {
 if (logicTableName.equals(oldTableRuleConfig.getLogicTable())) {
 ShardingTableRuleConfiguration newTableRuleConfig = new ShardingTableRuleConfiguration(oldTableRuleConfig.getLogicTable(), newActualDataNodes);
 newTableRuleConfig.setTableShardingStrategy(oldTableRuleConfig.getTableShardingStrategy());
 newTableRuleConfig.setDatabaseShardingStrategy(oldTableRuleConfig.getDatabaseShardingStrategy());
 newTableRuleConfig.setKeyGenerateStrategy(oldTableRuleConfig.getKeyGenerateStrategy());
 newTableRuleConfigList.add(newTableRuleConfig);
 } else {
 newTableRuleConfigList.add(oldTableRuleConfig);
 }
 });
 newAlgorithmConfig.setTables(newTableRuleConfigList);
 newAlgorithmConfig.setAutoTables(oldAlgorithmConfig.getAutoTables());
 newAlgorithmConfig.setBindingTableGroups(oldAlgorithmConfig.getBindingTableGroups());
 newAlgorithmConfig.setBroadcastTables(oldAlgorithmConfig.getBroadcastTables());
 newAlgorithmConfig.setDefaultDatabaseShardingStrategy(oldAlgorithmConfig.getDefaultDatabaseShardingStrategy());
 newAlgorithmConfig.setDefaultTableShardingStrategy(oldAlgorithmConfig.getDefaultTableShardingStrategy());
 newAlgorithmConfig.setDefaultKeyGenerateStrategy(oldAlgorithmConfig.getDefaultKeyGenerateStrategy());
 newAlgorithmConfig.setDefaultShardingColumn(oldAlgorithmConfig.getDefaultShardingColumn());
 newAlgorithmConfig.setShardingAlgorithms(oldAlgorithmConfig.getShardingAlgorithms());
 newAlgorithmConfig.setKeyGenerators(oldAlgorithmConfig.getKeyGenerators());
 newRuleConfigList.add(newAlgorithmConfig);
 }
 }
 // update context
 contextManager.alterRuleConfiguration(schemaName, newRuleConfigList);
 }
 /**
 * 샤딩 테이블 생성
 * @param logicTable  
 * @param tableName 실제 테이블 이름, 예: t_user_1
 * @return 생성 결과
 */
 public static boolean createShardingTable(ShardingTableCacheEnum logicTable, String tableName, LocalDateTime startTime, LocalDateTime endTime) {
 String index = tableName.replace(logicTable.logicTableName() + TABLE_SPLIT_SYMBOL,"");
 synchronized (logicTable.logicTableName().intern()) {
 // 테이블이 캐시에 없는 경우 테이블을 생성하고 캐시에 추가합니다.
 executeSql(Collections.singletonList("CREATE TABLE IF NOT EXISTS `" + tableName + "` LIKE `" + logicTable.logicTableName() + "`;"));
 // 레코드 추가
 ShardingRecord shardingRecord = new ShardingRecord();
 shardingRecord.setLogicTable(logicTable.logicTableName());
 shardingRecord.setActualTable(tableName);
 shardingRecord.setIndexNum(Long.valueOf(index));
 shardingRecord.setStartTime(startTime);
 shardingRecord.setEndTime(endTime);
 shardingRecordService.insert(shardingRecord);
 // 캐시 재로드
 tableNameCacheReload(logicTable);
 }
 return true;
 }
 /**
 * SQL 실행
 * @param sqlList SQL 
 */
 private static void executeSql(List<String> sqlList) {
 if (StringUtils.isEmpty(DATASOURCE_URL) || StringUtils.isEmpty(DATASOURCE_USERNAME) || StringUtils.isEmpty(DATASOURCE_PASSWORD)) {
 log.error(">>>>>>>>>> ERROR데이터베이스 연결이 잘못 구성되었습니다. 나중에 다시 시도하세요.,URL:{}, username:{}, password:{}", DATASOURCE_URL, DATASOURCE_USERNAME, DATASOURCE_PASSWORD);
 throw new IllegalArgumentException("데이터베이스 연결이 잘못 구성되었습니다. 나중에 다시 시도하세요.");
 }
 try (Connection conn = DriverManager.getConnection(DATASOURCE_URL, DATASOURCE_USERNAME, DATASOURCE_PASSWORD)) {
 try (Statement st = conn.createStatement()) {
 conn.setAutoCommit(false);
 for (String sql : sqlList) {
 st.execute(sql);
 }
 } catch (Exception e) {
 conn.rollback();
 log.error(">>>>>>>>>> ERROR데이터 테이블 생성 실행에 실패했습니다. 나중에 다시 시도하세요(이유):{}", e.getMessage(), e);
 throw new IllegalArgumentException("데이터 테이블 생성 실행에 실패했습니다. 나중에 다시 시도하세요.");
 }
 } catch (SQLException e) {
 log.error(">>>>>>>>>> ERROR데이터베이스 연결에 실패했습니다. 나중에 다시 시도하세요:{}", e.getMessage(), e);
 throw new IllegalArgumentException("데이터베이스 연결에 실패했습니다. 나중에 다시 시도하세요.");
 }
 }
}

하위 테이블에 대한 시간 제한 작업 생성 및 초기화

@Component
@Slf4j
public class TableInitJob {
 @Resource
 private ConfigProperty configProperty;
 private final String TABLE_SPLIT_SYMBOL = "_";
 @Resource
 private IShardingRecordService shardingRecordService;
 @Scheduled(cron = "${sharding.table.init.job:0 0 2 * * ?}")
 public void createTableAndDeleteExpiredTable() {
 // 향후 테이블 초기화 - 3일
 ShardingTableCacheEnum.logicTableNames().forEach(logicTable->{
 List<ShardingRecord> shardingRecords = shardingRecordService.queryAllShardingRecordByLogicName(logicTable);
 if (CollectionUtils.isEmpty(shardingRecords)){
 int index = 1;
 // 시작 시간부터 종료 시간까지 거꾸로 생성됨> 현재 시간+ configProperty.shardingTimeDys  
 LocalDateTime startTime = DateUtil.string2LocalDateTime(configProperty.getShardingStartTime(),null);
 LocalDateTime endTime = DateUtil.getEndDateTime(DateUtil.addDays(startTime, configProperty.getShardingTimeDys()));
 while (!endTime.isAfter(DateUtil.addDays(LocalDateTime.now(),configProperty.getShardingTimeDys()))){
 String tableName = logicTable + TABLE_SPLIT_SYMBOL + index;
 ShardingAlgorithmTool.createShardingTable(ShardingTableCacheEnum.of(logicTable),tableName,startTime,endTime);
 startTime = DateUtil.addDays(startTime,configProperty.getShardingTimeDys() + 1);
 endTime = DateUtil.addDays(endTime,configProperty.getShardingTimeDys() + 1);
 index++;
 }
 }else {
 // 마지막 시간부터 종료 시간까지 거꾸로 생성됨> 현재 시간+ configProperty.shardingTimeDys  
 ShardingRecord shardingRecord = shardingRecords.get(shardingRecords.size() - 1);
 int index = shardingRecord.getIndexNum().intValue() + 1;
 // 시작 시간부터 종료 시간까지 거꾸로 생성됨> 현재 시간+ configProperty.shardingTimeDys  
 LocalDateTime startTime = shardingRecord.getStartTime();
 LocalDateTime endTime = shardingRecord.getEndTime();
 while (!endTime.isAfter(DateUtil.addDays(LocalDateTime.now(),configProperty.getShardingTimeDys()))){
 String tableName = logicTable + TABLE_SPLIT_SYMBOL + index;
 startTime = DateUtil.addDays(startTime,configProperty.getShardingTimeDys() + 1);
 endTime = DateUtil.addDays(endTime,configProperty.getShardingTimeDys() + 1);
 ShardingAlgorithmTool.createShardingTable(ShardingTableCacheEnum.of(logicTable),tableName,startTime,endTime);
 index++;
 }
 }
 });
 }
}
Read next