Spring Boot 分庫(kù)分表策略示例展示
分庫(kù)分表是為了應(yīng)對(duì)大規(guī)模數(shù)據(jù)和高并發(fā)請(qǐng)求,提高系統(tǒng)的性能和可擴(kuò)展性。以下是如何在 Spring Boot 中實(shí)現(xiàn)分庫(kù)分表的詳細(xì)策略:
1. 分庫(kù)策略
分庫(kù)策略是將數(shù)據(jù)分散到多個(gè)數(shù)據(jù)庫(kù)實(shí)例中。常見(jiàn)的分庫(kù)策略有:
- 按用戶 ID:例如,通過(guò)用戶 ID 的哈希值決定存儲(chǔ)到哪個(gè)數(shù)據(jù)庫(kù)。
- 按業(yè)務(wù)類型:不同的業(yè)務(wù)或數(shù)據(jù)類型存儲(chǔ)到不同的數(shù)據(jù)庫(kù)。
- 按數(shù)據(jù)量:根據(jù)數(shù)據(jù)量將數(shù)據(jù)分散到多個(gè)數(shù)據(jù)庫(kù)中。
實(shí)現(xiàn)步驟:
- 配置多個(gè)數(shù)據(jù)源:
在 application.yml 文件中配置多個(gè)數(shù)據(jù)源的連接信息。
示例配置:
spring:
datasource:
dynamic:
primary: db1
datasource:
db1:
url: jdbc:mysql://localhost:3306/db1
username: root
password: password
db2:
url: jdbc:mysql://localhost:3306/db2
username: root
password: password
# 添加更多數(shù)據(jù)源- 動(dòng)態(tài)數(shù)據(jù)源路由:
創(chuàng)建 DynamicDataSource 類,繼承 AbstractRoutingDataSource,在 determineCurrentLookupKey 方法中返回當(dāng)前的數(shù)據(jù)源標(biāo)識(shí)。
DataSourceContextHolder 類用于存儲(chǔ)當(dāng)前的數(shù)據(jù)庫(kù)標(biāo)識(shí)。
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}
?
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
?
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
?
public static String getDataSourceType() {
return contextHolder.get();
}
?
public static void clearDataSourceType() {
contextHolder.remove();
}
}- 根據(jù)用戶 ID 選擇數(shù)據(jù)源:
使用工具類 DataSourceUtil 根據(jù)用戶 ID 計(jì)算出數(shù)據(jù)源標(biāo)識(shí)。
public class DataSourceUtil {
private static final int TOTAL_DATASOURCES = 8;
?
public static String getDataSourceNameByUserId(Long userId) {
int index = (int) (userId % TOTAL_DATASOURCES) + 1;
return "db" + index;
}
}- 配置數(shù)據(jù)源:
在配置類中創(chuàng)建 DynamicDataSource 實(shí)例,并配置各個(gè)數(shù)據(jù)源。
@Configuration
public class DataSourceConfig {
@Autowired
@Qualifier("db1DataSource")
private DataSource db1DataSource;
?
@Autowired
@Qualifier("db2DataSource")
private DataSource db2DataSource;
?
// 更多數(shù)據(jù)源...
?
@Bean
public DataSource dataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("db1", db1DataSource);
targetDataSources.put("db2", db2DataSource);
// 更多數(shù)據(jù)源...
?
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(db1DataSource);
return dynamicDataSource;
}
?
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}2. 分表策略
分表策略是將數(shù)據(jù)分散到多個(gè)表中。常見(jiàn)的分表策略有:
- 按時(shí)間分表:例如,每個(gè)月一個(gè)表。
- 按 ID 范圍分表:例如,每 10000 條數(shù)據(jù)一個(gè)表。
- 按用戶 ID 哈希:例如,將用戶數(shù)據(jù)分散到多個(gè)表中。
實(shí)現(xiàn)步驟:
- 生成表名:
創(chuàng)建工具類 TableNameUtil 根據(jù)分表策略生成表名。
public class TableNameUtil {
public static String getTableNameByMonth(String baseTableName, LocalDate date) {
String month = date.format(DateTimeFormatter.ofPattern("yyyy_MM"));
return baseTableName + "_" + month;
}
?
public static String getTableNameByIdRange(String baseTableName, Long id) {
int range = (int) (id / 10000);
return baseTableName + "_" + range;
}
?
public static String getTableNameByUserId(String baseTableName, Long userId) {
int tableIndex = (int) (userId % 8);
return baseTableName + "_" + tableIndex;
}
}- 在數(shù)據(jù)訪問(wèn)層使用分表策略:
在數(shù)據(jù)訪問(wèn)層根據(jù)生成的表名執(zhí)行數(shù)據(jù)庫(kù)操作。
@Repository
public class OrderRepository {
private final JdbcTemplate jdbcTemplate;
?
public OrderRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
?
public void saveOrder(Order order) {
String dataSourceName = DataSourceUtil.getDataSourceNameByUserId(order.getUserId());
DataSourceContextHolder.setDataSourceType(dataSourceName);
?
String tableName = TableNameUtil.getTableNameByUserId("orders", order.getUserId());
String sql = "INSERT INTO " + tableName + " (id, order_date, amount) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, order.getId(), order.getOrderDate(), order.getAmount());
?
DataSourceContextHolder.clearDataSourceType();
}
}總結(jié)
- 分庫(kù):將數(shù)據(jù)存儲(chǔ)到多個(gè)數(shù)據(jù)庫(kù)中,通過(guò)動(dòng)態(tài)數(shù)據(jù)源選擇和路由來(lái)決定當(dāng)前使用的數(shù)據(jù)庫(kù)。
- 分表:將數(shù)據(jù)存儲(chǔ)到多個(gè)表中,根據(jù)分表策略生成動(dòng)態(tài)表名。
- 實(shí)現(xiàn):配置多個(gè)數(shù)據(jù)源,使用動(dòng)態(tài)數(shù)據(jù)源路由,創(chuàng)建工具類生成表名,并在數(shù)據(jù)訪問(wèn)層應(yīng)用這些策略。
這種分庫(kù)分表策略可以有效地提高系統(tǒng)的性能和可擴(kuò)展性,尤其適用于大規(guī)模數(shù)據(jù)處理場(chǎng)景。
到此這篇關(guān)于Spring Boot 分庫(kù)分表策略示例展示的文章就介紹到這了,更多相關(guān)Spring Boot 分庫(kù)分表策略內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot?如何使用sharding?jdbc進(jìn)行分庫(kù)分表
- SpringBoot實(shí)現(xiàn)分庫(kù)分表
- SpringBoot整合sharding-jdbc實(shí)現(xiàn)自定義分庫(kù)分表的實(shí)踐
- SpringBoot整合sharding-jdbc實(shí)現(xiàn)分庫(kù)分表與讀寫(xiě)分離的示例
- Spring Boot 集成 Sharding-JDBC + Mybatis-Plus 實(shí)現(xiàn)分庫(kù)分表功能
- springboot jpa分庫(kù)分表項(xiàng)目實(shí)現(xiàn)過(guò)程詳解
- Springboot2.x+ShardingSphere實(shí)現(xiàn)分庫(kù)分表的示例代碼
- SpringBoot 2.0 整合sharding-jdbc中間件實(shí)現(xiàn)數(shù)據(jù)分庫(kù)分表
相關(guān)文章
詳解Java 反射和反射的應(yīng)用場(chǎng)景
這篇文章主要介紹了Java 反射和反射的應(yīng)用場(chǎng)景的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java反射的相關(guān)知識(shí),感興趣的朋友可以了解下2020-08-08
Java模擬實(shí)現(xiàn)QQ三方登錄(單點(diǎn)登錄2.0)
這篇文章主要為大家詳細(xì)介紹了Java模擬實(shí)現(xiàn)QQ三方登錄,單點(diǎn)登錄2.0,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
10個(gè)Java解決內(nèi)存溢出OOM的方法詳解
在Java開(kāi)發(fā)過(guò)程中,有效的內(nèi)存管理是保證應(yīng)用程序穩(wěn)定性和性能的關(guān)鍵,不正確的內(nèi)存使用可能導(dǎo)致內(nèi)存泄露甚至是致命的OutOfMemoryError(OOM),下面我們就來(lái)學(xué)習(xí)一下有哪些解決辦法吧2024-01-01
詳解springboot項(xiàng)目帶Tomcat和不帶Tomcat的兩種打包方式
這篇文章主要介紹了詳解springboot項(xiàng)目帶Tomcat和不帶Tomcat的兩種打包方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Springboot整合微信支付(訂單過(guò)期取消及商戶主動(dòng)查單)
本文主要介紹了Springboot整合微信支付(訂單過(guò)期取消及商戶主動(dòng)查單),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07

