IT/Spring

DB Replication에 따른 Spring 설정

eddie_factory 2021. 12. 10. 14:33
반응형

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<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("master", masterDataSource);
        dataSourceMap.put("slave", slaveDataSource);

        routingDataSource.setTargetDataSources(dataSourceMap);
        routingDataSource.setDefaultTargetDataSource(masterDataSource);

        return routingDataSource;
    }
}

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

 

 

Replication의 장단점

장점

 - 성능향상 효과가 있습니다. (read와 write를 분리하여 부하를 줄여줍니다)

 - master DB에 오류가 발생했을 경우, 분리하여  slave 기준으로 복구할 수 있습니다.(스냅샷으로 복구 가능하나,  slave 기준으로 복구시 정합성이 더 높음)

단점 

 - 쓰기지연에 따라 master와 slave 데이터가 정확히 일치하지 않을 수 있습니다.

 - master DB 오류 발생시, fail over하여 slave DB를 사용할 수 없습니다. 

 

데이터 정합성을 향상시키기 위해

지연 쿼리의 성능을 향상, 데이터 분리, 하드웨어 scale up을 시킬수 있으며  select더라도 실시간으로 제공해야하는 data의 경우는 master를 활용하도록 처리합니다.

 

참조 블로그

https://k3068.tistory.com/102#AbstractRoutingDataSource%--Bean%--%EB%--%B-%EB%A-%-D%ED%--%--%EA%B-%B-

 

aws DB replication 관련

https://developer88.tistory.com/317

반응형