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í)例中。常見的分庫(kù)策略有:
- 按用戶 ID:例如,通過用戶 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è)表中。常見的分表策略有:
- 按時(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ù)訪問層使用分表策略:
在數(shù)據(jù)訪問層根據(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ù)中,通過動(dòng)態(tài)數(shù)據(jù)源選擇和路由來決定當(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ù)訪問層應(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ù)分表與讀寫分離的示例
- Spring Boot 集成 Sharding-JDBC + Mybatis-Plus 實(shí)現(xiàn)分庫(kù)分表功能
- springboot jpa分庫(kù)分表項(xiàng)目實(shí)現(xiàn)過程詳解
- 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-08Java模擬實(shí)現(xiàn)QQ三方登錄(單點(diǎn)登錄2.0)
這篇文章主要為大家詳細(xì)介紹了Java模擬實(shí)現(xiàn)QQ三方登錄,單點(diǎn)登錄2.0,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-0610個(gè)Java解決內(nèi)存溢出OOM的方法詳解
在Java開發(fā)過程中,有效的內(nèi)存管理是保證應(yīng)用程序穩(wěn)定性和性能的關(guān)鍵,不正確的內(nèi)存使用可能導(dǎo)致內(nèi)存泄露甚至是致命的OutOfMemoryError(OOM),下面我們就來學(xué)習(xí)一下有哪些解決辦法吧2024-01-01詳解springboot項(xiàng)目帶Tomcat和不帶Tomcat的兩種打包方式
這篇文章主要介紹了詳解springboot項(xiàng)目帶Tomcat和不帶Tomcat的兩種打包方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Springboot整合微信支付(訂單過期取消及商戶主動(dòng)查單)
本文主要介紹了Springboot整合微信支付(訂單過期取消及商戶主動(dòng)查單),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07