springboot Datasourceを分ける

今回は、DatasourceをMaster、Slaveに分ける方法について調べていきたいと思います。

DataSourceとは

Javaのjavax.sql.DataSource インターフェースは、データベース接続を操作する標準的な方法を提供します。伝統的に、”DataSource” は、URLといくつかの資格情報を使用してデータベース接続を確立します。

DataSourceを分ける

application.yml作成

spring:
  datasource:
    master:
        username: root
        password: password
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/sampledb
    slave:
        username: root
        password: password
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3307/sampledb

MasterとSlaveのDBを2つ使用するために、Datasource生成作業を実装しなければなりません。

DataSourceConfig作成

@Configuration
public class DataSourceConfig {

  @Bean(name = "dataSource")
  public DataSource dataSource(
      @Autowired @Qualifier("routingDataSource") DataSource routingDataSource) {
    return new LazyConnectionDataSourceProxy(routingDataSource);
  }

  @Bean(name = "routingDataSource")
  @Primary
  public DataSource routingDataSource(
      @Autowired @Qualifier("masterDataSource") DataSource masterDataSource,
      @Autowired @Qualifier("slaveDataSource") DataSource slaveDataSource) {

    RoutingDataSource routingDataSource = new RoutingDataSource();

    Map<Object, Object> dataSourceMap = new HashMap<>();
    dataSourceMap.put("master", masterDataSource);
    dataSourceMap.put("slave", slaveDataSource);
    routingDataSource.setTargetDataSources(dataSourceMap);
    routingDataSource.setDefaultTargetDataSource(masterDataSource);

    return routingDataSource;
  }

  @Bean(name = "masterDataSource")
  @ConfigurationProperties(prefix = "spring.datasource.master")
  public DataSource masterDataSource() {
    return DataSourceBuilder.create().type(HikariDataSource.class).build();
  }

  @Bean(name = "slaveDataSource")
  @ConfigurationProperties(prefix = "spring.datasource.slave")
  public DataSource slaveDataSource() {
    return DataSourceBuilder.create().build();
  }
}
  • 設定クラスなので「Configuration」アノテーションを付与します。
  • routingDataSource
    • MasterとSlaveのDataSourceとして登録します。
    • デフォルトとしてはMaster DataSourceを指定します。
  • masterDataSource
    • プロパティからmaster DB情報を取得し、DataSourceを返します。
    • 「masterDataSource」としてBeanを登録します。
  • slaveDataSource
    • masterDataSourceメソッドと同様ですが、master db情報ではなく、slave db情報でDataSourceを生成して返します。

RoutingDataSource作成

public class RoutingDataSource extends AbstractRoutingDataSource {
  @Override
  protected Object determineCurrentLookupKey() {
    return TransactionSynchronizationManager.isCurrentTransactionReadOnly() ? "slave" : "master";
  }
}
  • AbstractRoutingDataSource:照会keyで登録されているDataSourceの中で一つを呼び出せます。
  • determineCurrentLookupKey:現在、照会キーを返却できるように実装しなければなりません。
    • ここではMasterとSlaveと指定しています。
    • readOnly属性の場合はslave Datasourceが返却されるように実装します。
  • DataSourceConfigクラスのroutingDataSourceメソッドから呼ばれます。

使い方

    @Transactional(readOnly = true)
    public List<Some> get(){
        return someRepository.findAll();
    }

    public int update() {
        SomEntity someEntity = new SomeEntity();
        return someRepository.update(someEntity);
    }
  • Transactionalアノテーションの属性として「readOnly=true」なので、RoutingDataSourceによるslave Datasourceを利用してデータを取得します。
  • update:何も指定していないため、master Datasourceを利用してデータをアップデートします。

参考

https://spring.pleiades.io/spring-boot/docs/2.1.4.RELEASE/reference/html/boot-features-sql.html

コメントを残す