Мы столкнемся с большим объемом данных в наших базах данных mariadb.Чтобы преодолеть проблемы с резервным копированием и операциями ddl, у нас была идея хранить данные в нескольких базах данных.В основном у нас будет база данных с краткосрочными данными (например, за последние 30 дней, с именем short_term) и еще одна с остальными данными (с именем long_term).Очевидно, что данные должны быть перемещены из short_term в long_term, но это должно быть достижимо.
Проблема, с которой я сталкиваюсь в настоящее время на прототипе, заключается в том, что я могу подключиться к short_term, но не могу переключиться на long_term, если дляПример хочу запросить их обоих (например, get (), где я не могу найти его в базе данных short_term).
Я настроил это так (оба работают независимо, но не с контекстом базы данных коммутатора):
HistoryAwareRoutingSource:
public class HistoryAwareRoutingSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return ThreadLocalStorage.getDatabaseType();
}
}
ThreadLocalStorage
public class ThreadLocalStorage {
private static ThreadLocal<String> databaseType = new ThreadLocal<>();
public static void setDatabaseType(String databaseTypeName) {
databaseType.set(databaseTypeName);
}
public static String getDatabaseType() {
return databaseType.get();
}
}
DatasourceConfiguration
@Configuration
public class DatasourceConfiguration {
@Value("${spring.datasource.url}")
private String db1Url;
@Value("${spring.datasource.username}")
private String db1Username;
@Value("${spring.datasource.password}")
private String db1Password;
@Value("${spring.datasource.driver-class-name}")
private String db1DriverClassName;
@Value("${spring.datasource.connectionProperties}")
private String db1ConnectionProps;
@Value("${spring.datasource.sqlScriptEncoding}")
private String db1Encoding;
@Value("${spring.datasource2.url}")
private String db2Url;
@Value("${spring.datasource2.username}")
private String db2Username;
@Value("${spring.datasource2.password}")
private String db2Password;
@Value("${spring.datasource2.driver-class-name}")
private String db2DriverClassName;
@Value("${spring.datasource2.connectionProperties}")
private String db2ConnectionProps;
@Value("${spring.datasource2.sqlScriptEncoding}")
private String db2Encoding;
@Bean
public DataSource dataSource() {
HistoryAwareRoutingSource historyAwareRoutingSource = new HistoryAwareRoutingSource();
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put("PRIMARY", dataSource1());
dataSourceMap.put("SECONDARY", dataSource2());
historyAwareRoutingSource.setDefaultTargetDataSource(dataSource1());
historyAwareRoutingSource.setTargetDataSources(dataSourceMap);
historyAwareRoutingSource.afterPropertiesSet();
return historyAwareRoutingSource;
}
private DataSource dataSource1() {
HikariDataSource primary = new HikariDataSource();
primary.setInitializationFailTimeout(0);
primary.setMaximumPoolSize(5);
primary.setDriverClassName(db1DriverClassName);
primary.setJdbcUrl(db1Url);
primary.setUsername(db1Username);
primary.setPassword(db1Password);
primary.addDataSourceProperty("connectionProperties", db1ConnectionProps);
primary.addDataSourceProperty("sqlScriptEncoding", db1Encoding);
return primary;
}
private DataSource dataSource2() {
HikariDataSource secondary = new HikariDataSource();
secondary.setInitializationFailTimeout(0);
secondary.setMaximumPoolSize(5);
secondary.setDriverClassName(db2DriverClassName);
secondary.setJdbcUrl(db2Url);
secondary.setUsername(db2Username);
secondary.setPassword(db2Password);
secondary.addDataSourceProperty("connectionProperties", db2ConnectionProps);
secondary.addDataSourceProperty("sqlScriptEncoding", db2Encoding);
return secondary;
}
}
Тогда у меня есть класс RestController, подобный этому:
@RestController
@RequestMapping(value = "/story")
@RequiredArgsConstructor
public class MultiDBController {
@Autowired
private StoryService storyService;
@GetMapping("/create")
@UsePrimaryStorage
public ResponseEntity<StoryDTO> createEntity() {
setPrimaryDB();
return ResponseEntity.ok(storyService.createOne());
}
private void setPrimaryDB() {
// TODO destroy the current db connection or hand it back to the pool so the next time a connect is taken it is the PRIMARY Datasource?
ThreadLocalStorage.setDatabaseType("PRIMARY");
}
private void setSecondaryDB() {
// TODO destroy the current db connection or hand it back to the pool so the next time a connect is taken it is the PRIMARY Datasource?
ThreadLocalStorage.setDatabaseType("SECONDARY");
}
@GetMapping("/{storyId}")
public ResponseEntity<StoryDTO> get(@PathVariable UUID storyId) {
// try to find in primary db
setPrimaryDB();
Optional<StoryDTO> storyOptional = storyService.findOne(storyId);
if (!storyOptional.isPresent()) {
setSecondaryDB();
Optional<StoryDTO> storyOptionalSecondary = storyService.findOne(storyId);
if(storyOptionalSecondary.isPresent()) {
return ResponseEntity.ok(storyOptionalSecondary.get());
} else {
return ResponseEntity.notFound().build();
}
}
return ResponseEntity.ok(storyOptional.get());
}
}
Итак, вопрос в том, как мне реализовать TODO