DB Replication에 따른 Spring 설정

DB Replication에 따른 Spring 설정

반응형

1. DB Replication

- 데이터베이스 이중화 방식 중 하나로 하나의 Master DB와 여러대의 Slave DB로 구성.

Master DB에 데이터의 변경이 감지되면 Master DB의 로그를 기반으로 Slave DB에 복제 합니다.

- 서비스 사용자의 증가로 트래픽이 늘어날 경우 DB에 부하가 생겨 속도 저하, time out 에러가 발생할 수 있습니다.

- Replication을 통해 select요청은 Slave DB(읽기전용)에서 처리, CUD는 Master DB에서 처리할 수 있도록 분리하여 트래픽을 분산되도록 합니다.

Spring의 @Transactional 설정에 따라 설정하는 DB가 달라지게 됩니다.

@Transactional(readOnly = true) 인 경우는 Slave DB 접근

@Transactional(readOnly = false) 인 경우에는 Master DB 접근

2. application.yml 설정

spring: datasource: master: url: driver-class-name: username: password: slave: url: driver-class-name: username: password:

기본 형식은 spring.datasource.url 과 같은 형태로 진행되지만 Replication된 DB를 사용해야하므로 master, slave를 개별 설정합니다. (커스텀한다고 생각...)

3.datasource bean 등록

@Configuration public class DatabaseConfig { @Primary @Bean(name = "masterDataSource") @ConfigurationProperties(prefix = "spring.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "slaveDataSource") @ConfigurationProperties(prefix = "spring.datasource.slave") public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); } }

@ConfigurationProperties를 통해 yml에 지정한 설정을 입력하여 DataSource를 생성합니다.

@Primary는 같은 bean이 여러개일 경우 우선적으로 등록될 bean을 설정한다고 합니다.

4. AbstractRoutingDataSource 구현

public class ReplicationRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { boolean isReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); if(isReadOnly) { return "slave"; } else { return "master"; } }

AbstractRoutingDataSource는 key 기반으로 등록된 Datasource 중 하나를 호출을 하게 해줍니다.

이를 상속받아 determineCurrentLookupKey() 을 오버라이드하여 어떤 ContextHolder를 통해서 값을 매칭시킬지 구현하면 됩니다.

5. AbstractRoutingDataSource Bean 등록

@Configuration public class DatabaseConfig { ... @Bean(name = "routingDataSource") public DataSource routingDataSource(@Qualifier("masterDataSource") DataSource masterDataSource, @Qualifier("slaveDataSource") DataSource slaveDataSource) { ReplicationRoutingDataSource routingDataSource = new ReplicationRoutingDataSource(); Map dataSourceMap = new HashMap<>(); dataSourceMap.put("master", masterDataSource); dataSourceMap.put("slave", slaveDataSource); routingDataSource.setTargetDataSources(dataSourceMap); routingDataSource.setDefaultTargetDataSource(masterDataSource); return routingDataSource; } }

위의 AbstractRoutingDataSource를 상속받아 구현한 메소드를 Bean으로 생성합니다.

반응형

from http://eddies.tistory.com/35 by ccl(A) rewrite - 2021-12-10 15:01:44