on
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