天天看點

SpringBoot內建ShardingJDBC系列【4】—— 內建多資料源動态切換

文章隻負責講解sharding的相關配置,springboot其他的配置自己解決!!

文章内容将分開釋出,便于平時查閱。

內建多資料源動态切換

  1. 為什麼有了sharding還要配置多資料源?

    根據之前SpringBoot內建ShardingJDBC系列【2】—— 基于yaml基本配置這篇文章中提到過這個問題,對于隻有部分資料庫分庫分表,為什麼需要将不分庫分表的表也配置在分片規則中。

因為ShardingSphere是将多個資料源合并為一個統一的邏輯資料源。是以即使不分庫分表的部分,不配置分片規則ShardingSphere即無法精确的斷定應該路由至哪個資料源。 但是ShardingSphere提供了兩種變通的方式,有助于簡化配置。

方法一:配置default-data-source,凡是在預設資料源中的表可以無需配置在分片規則中,ShardingSphere将在找不到分片資料源的情況下将表路由至預設資料源。

缺點:這種方法有一個緻命的缺點,就是如果查詢的表不在設定的預設資料源中,還是需要将表配置到分片規則中。除非你的需求是決定将所有不需要進行分片的表都放在預設資料源裡,那麼倒是可以這麼做,否則你就得一個一個配置表的分片規則了。

方法2:将不參與分庫分表的資料源獨立于ShardingSphere之外,在應用中使用多個資料源分别處理分片和不分片的情況。

優點:将不分片的資料源獨立出來,開發者可以通過多資料源自主選擇處理不同情況,僅需要簡單配置後加個注解即可。我接下來所要講的就是這個!!!

  1. 添加多資料源的依賴和配置:

    這裡選擇的是baomidou團隊開發的一個基于springboot的快速內建多資料源的啟動器,詳細文檔可前往官方文檔介紹。

(1)依賴:

<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
			<version>${dynamic.datasource.version}</version>
		</dependency>		

		<sharding.jdbc.version>4.1.0</sharding.jdbc.version>
           

(2)配置:

這裡建立一個新的application-dynamic-datasource.yml檔案,然後在application.yml的spring:profiles:include:引入即可,編輯如下:

spring:
  datasource:
    dynamic:
      datasource:
        master:
          type: com.alibaba.druid.pool.DruidDataSource
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/sharding_test_1?useUnicode=true&useSSL=false&characterEncoding=utf8&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
          username: root
          password: 123456

        slave:
          type: com.alibaba.druid.pool.DruidDataSource
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/sharding_test_2?useUnicode=true&useSSL=false&characterEncoding=utf8&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
          username: root
          password: 123456

      primary: master # 設定預設的資料源或者資料源組,預設值即為master
      strict: false # 設定嚴格模式,預設false不啟動. 啟動後在未比對到指定資料源時候會抛出異常,不啟動則使用預設資料源

           

(3)內建Sharding:從上面那一步完成後,我們便可以通過@DS()注解來動态的選擇資料源了。但是,也隻能使用上面的master和slave兩個資料源。如果要內建Sharding的話,也就是将Sharding資料源也加入到dynamic-datasource的管理中來。直接貼代碼:

/**
 * @author KLAY_
 * @date 2020/09/03 14:43
 */
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class,
        SpringBootConfiguration.class})
public class DataSourceConfiguration {

    /**
     * 分表資料源名稱
     */
    private static final String SHARDING_DATASOURCE_NAME = "sharding";

    /**
     * 動态資料源配置項
     */
    @Autowired
    private DynamicDataSourceProperties properties;

    /**
     * shardingjdbc有四種資料源,需要根據業務注入不同的資料源
     * 1. 未使用分片, 脫敏的名稱(預設): shardingDataSource;
     * 2. 主從資料源: masterSlaveDataSource;
     * 3. 脫敏資料源:encryptDataSource;
     * 4. 影子資料源:shadowDataSource
     */
    @Lazy
    @Resource(name = "shardingDataSource")
    AbstractDataSourceAdapter shardingDataSource;

    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() {
        Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
        return new AbstractDataSourceProvider() {
            @Override
            public Map<String, DataSource> loadDataSources() {
                Map<String, DataSource> map = createDataSourceMap(datasourceMap);
                map.put(SHARDING_DATASOURCE_NAME, shardingDataSource);  /// 這裡将shardingjdbc管理的資料源交給dynamic-datasource動态資料源去管理
                return map;
            }
        };
    }

    /**
     * 将dynamic-datasource動态資料源設定為首選的
     * 當spring存在多個資料源的時候,自動注入的是首選資料源
     * 這樣之後可以支援sharding-jdbc原生的配置方式
     * @param dynamicDataSourceProvider
     * @return
     */
    @Primary
    @Bean
    public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        dataSource.setPrimary(properties.getPrimary());
        dataSource.setStrict(properties.getStrict());
        dataSource.setStrategy(properties.getStrategy());
        dataSource.setProvider(dynamicDataSourceProvider);
        dataSource.setP6spy(properties.getP6spy());
        dataSource.setSeata(properties.getSeata());
        return dataSource;
    }

}
           

之後,我們對需要進行分片處理的表,則可以在類或者方法直接加上一個@DS(“sharding”)注解,即可進行分片處理;而對于不需要分片的表,我隻需要@DS(“其他的資料源”)即可。

遇過的坑(注意):
@DS()注解的優先級上,方法優于類。
對于多資料源之間的事務、分布式事務,會存在一些問題。後續會再更新這一友善的。

事先說明,該系列下的所有文章均為作者查閱很多配置資料後整理得出,主要用于個人記錄學習的配置資料不涉及原理,僅作參考。

繼續閱讀