본문으로 바로가기

실제 현업에서는 Master, Slave로 이중화를 기본으로 세팅되어 있는걸 많이 보았다. Master는 Write용도, Slave는 Read용도로 써서 트래픽을 분산 처리하는 장점정도는 알고있지만, 상세한 내용에 대해서는 알지 못했다.

그래서 기존 토이 프로젝트에 MySQL Replication(복제) 공부도 할 겸 Master, Slave로 이중화 작업을 시도해보았다.

 

 

<Replication 기본 개념>

일단 MySQL Replication의 동작 원리에 대해서 우선 살펴보자.

MySQL의 Replication은 비동기 복제 방식을 사용하고있다.

 

- Master에서 변경이 있으면 이를 바이너리 로그에 저장하고 이를 비동기적으로 Slave에게 전송한다.

- Slave에서는 이를 받아 릴레이 로그에 저장한 후 변경사항을 스토리지 엔진에 반영한다.

cloudrain21.com/mysql-replication

더 자세한 내용은 위 블로그 참조!!

 

핵심은 Master에게는 데이터 동시성이 아주 높게 요구되는 트랜잭션을 담당하고, Slave에게는 데이터 동시성이 꼭 보장될 필요 없는 경우에 읽기 전용으로 데이터를 가져오게 된다는 것이다.

 

 

<Replication 실습 간단 요약>

- Docker를 활용해 MySQL 컨테이너를 Master, Slave 2대를 띄운다. 간편하게 docker-compose를 활용해 한번에 생성하는게 나은듯

- Slave 서버에서는 Master의 데이터를 읽어오기 위한 ip 등의 정보를 설정해줘야 한다.

- 예시

CHANGE MASTER TO 
MASTER_HOST='{master network ip address}', 
MASTER_USER='root', 
MASTER_PASSWORD='password', 
MASTER_LOG_FILE='mysql-bin.000001', 

...

- 연동이 정상적으로 되었다면 Master 서버에 데이터를 Write 했을때, Slave 서버에서도 동일하게 반영되는걸 확인할 수 있다.

 

 

<SpringBoot Master, Slave Transaction 분리>

@Transactional(readOnly = true)
public List<Board> getBoard() {
	return boardRepository.findAll();
}

@Transactional
public void insertBoard(Board board) {
	boardRepository.save(board);
}

@Transactional readOnly 값에 따라 master, slave 라우팅이 정해진다.

true이면 slave db, false이면 master db로 요청이 전해진다. 저 옵션 기준으로 처리하기 위해서는 추가적인 설정 작업이 필요할것같지 않은가? 일단은 예상만 해보고 하나씩 적용해보자

 

 

1. master, slave로 db가 분리되어 있으니 application.yml에 datasource를 각각 분리해서 커넥션 생성을 한다.

  datasource:
    master:
      hikari:
      ...
    slave:
      hikari:
      ...

2. spring 기본 커넥션풀인 tomcat-jdbc가 아닌 hikaricp를 활용하기 때문에 hikari 관련 bean을 직접 생성해줘야한다. 실제 yml 정보가 매핑되는 필드는 HikariDataSource가 상속하고 있는 HikariConfig에 존재한다.

@Configuration
public class DataSourceConfig {

    public static final String MASTER_DATASOURCE = "masterDataSource";
    public static final String SLAVE_DATASOURCE = "slaveDataSource";

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

    @Bean(SLAVE_DATASOURCE)
    @ConfigurationProperties(prefix = "spring.datasource.slave.hikari")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create()
                .type(HikariDataSource.class)
                .build();
    }
    
    ...
}

3. 위에서 언급했던 transactional readonly 옵션으로 라우팅 처리하기 위한 설정이다.

@Configuration
public class RoutingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) ? "slave" : "master";
    }
}

 

핵심 코드는 이정도이다. 서버 띄워서 write, read 메소드 각각 실행해보면 라우팅이 정상적으로 잘 처리되는걸 볼수있다.

실제로 라우팅 되는지 로그를 보고싶다면 

 

general_log 값을 OFF => ON 으로 수정하면 실시간 로그를 모니터링 할 수 있다. 해당 내용은 log_file에서 확인 가능하다.

 

 

 

참고 링크

https://mytalkhome.tistory.com/840

 

[MariaDB] 마리아DB slave , 복제(Replication) 구성하기

master - slave 를 구성해야 하는 이유가 뭘까요?크게 두가지로 볼 수 있을듯 합니다.1. 나름 백업2. 분산처리( 쓰기는 마스터만, 읽기는 슬레이브에서만 )분산처리란 결국 안정성 향상이라고 볼수도

mytalkhome.tistory.com

https://huisam.tistory.com/entry/mysql-replication

 

MySql - Master Slave Replication 구조 만들어보기

MySQL Master Slave 구조 만들어보기 일반적으로 디비에 대한 트래픽 분산을 위해서 Mysql Replication 를 통해서 트래픽 집중 문제를 해결할 수 있는데요 Master에게는 데이터 동시성이 아주 높게 요구되는

huisam.tistory.com

https://velog.io/@ililil9482/Spring-Boot-MySqlMaster-Slave-%EA%B5%AC%EC%84%B1

 

Spring Boot + MySql(Master + Slave) 구성 (Feat. Mybatis)

이전에는 Redis를 사용하여 마스터 슬레이브 구조를 구성해보았다. 이 구조를 본 DB인 MySql에도 적용해보려고 한다. 참고 [Spring-boot] Master - Slave 구조에 따른 Read, Write 분기 🐳 Docker 🐋 Mysql 서버 생

velog.io

https://k3068.tistory.com/102#AbstractRoutingDataSource%--%EA%B-%AC%ED%--%--

https://tjdrnr05571.tistory.com/14

 

[#8] Mysql Replication - Spring에서 Master/Slave 이중화 with Docker

이글에선 단일서버에서 Mysql Replication을 port를 나누어 하는 방법을 다룹니다. 목차 - 내 프로젝트에서 Mysql Replication을 사용해야 하는 이유 - Mysql Replication의 동작 원리 - Docker로 Mysql 컨테이너 두개

tjdrnr05571.tistory.com