
오늘은 간단하게 Docker, Mysql을 통해 Replication을 구현해보겠습니다. 현업에서는 AWS RDS를 통해서 구현을 해보았는데 온프레미스에 구현한다 생각해보고 진행해 보겠습니다.
먼저 Master DB 1대, Slave DB 2대를 docker-compose를 통해 구현해보도록 하겠습니다.
services:
master:
image: mysql:8.0
container_name: mysql-master
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: board
ports:
- "3306:3306"
volumes:
- /Users/include-hoany/Desktop/Coding/Replication/master/my.cnf:/etc/mysql/my.cnf
networks:
- mysql-net
slave1:
image: mysql:8.0
container_name: mysql-slave1
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: board
ports:
- "3307:3306"
volumes:
- /Users/include-hoany/Desktop/Coding/Replication/slaveOne/my.cnf:/etc/mysql/my.cnf
depends_on:
- master
networks:
- mysql-net
slave2:
image: mysql:8.0
container_name: mysql-slave2
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: board
ports:
- "3308:3306"
volumes:
- /Users/include-hoany/Desktop/Coding/Replication/slaveTwo/my.cnf:/etc/mysql/my.cnf
depends_on:
- master
networks:
- mysql-net
networks:
mysql-net:
Mysql 8.0 환경이고 3306, 3307, 3308포트를 차례로 사용합니다. 모든 디비가 새롭게 생성되면 기본적으로 board디비가 생성되도록 하였고 networks는 mysql-net으로 연결하도록 하겠습니다. 그리고 가장 중요한 cnf설정을 master, slave1, slave2 역할에 맞게 설정한 cnf파일을 마운트 합니다. cnf파일 내용은 아래와 같습니다.
/master/my.cnf // master my.cnf
[mysqld]
server-id=1 // DB를 식별을 위한 고유 ID
log-bin=mysql-bin // 페일오버를 대비한 슬레이브 바이너리 파일 기록 접두어 설정
binlog-do-db=board // 바이너리에 저장할 디비 설정
/slaveOne/mycnf // slave1 my.cnf
[mysqld]
server-id=2 // DB를 식별을 위한 고유 ID
relay-log=relay-log // 마스터 디비로부터 받은 바이너리 파일을 리플레이로그로 저장할때 접두어
log-bin=mysql-bin // 페일오버를 대비한 슬레이브 바이너리기록 활성화및 접두어 설정
replicate-do-db=board // 마스터 디비에서 복제할 디비 설정
binlog-do-db=board // 바이너리에 저장할 디비 설정
read-only=1 // 슬레이브는 읽기 전용으로 설정 단 ROOT는 계정은 Insert, Delete, Update가능
/slaveTwo/my.cnf // slave2 my.cnf
[mysqld]
server-id=3 // DB를 식별을 위한 고유 ID
relay-log=relay-log // 마스터 디비로부터 받은 바이너리 파일을 리플레이로그로 저장할때 접두어
log-bin=mysql-bin // 페일오버를 대비한 슬레이브 바이너리기록 활성화및 접두어 설정
replicate-do-db=board // 마스터 디비에서 복제할 디비 설정
binlog-do-db=board // 바이너리에 저장할 디비 설정
read-only=1 // 슬레이브는 읽기 전용으로 설정 단 ROOT는 계정은 Insert, Delete, Update가능
master/my.cnf 설정중 가장 중요한 설정은 binlog-do-db=board입니다. 바이너리에 기록할 DB를 설정합니다. 해당 목록에 존재하지 않은 DB는 바이너리에 변경사항이 기록되지 않아 Slave DB에 복제되지 않게됩니다.

docker-compose up -d를 통해 도커 컨테이너를 구성해 줍니다.

docker exec -it mysql-master mysql -u root -p 명령어를 통해 마스터 디비로 접근하여 Slave DB들이 Master DB에 접근할 수 있도록 계정을 생성합니다.
CREATE USER 'replica_user'@'%' IDENTIFIED WITH mysql_native_password BY 'replica_pass';
GRANT REPLICATION SLAVE ON *.* TO 'replica_user'@'%';
FLUSH PRIVILEGES;
Mysql 8.0부터는 기본 인증방식이 caching_sha2_password로 변경되었지만 이번 시간에는 간단한 인증방식을 사용하기 위해 mysql_native_password로 설정하여 계정을 생성합니다.
-- Master DB 바이너리 정보 확인
SHOW MASTER STATUS;

master my.cnf log-bin=mysql-bin 설정에 따른 접두어가 붙은 바이너리 파일명을 확인합니다. 그리고 중요한 Position을 확인해 줍니다. 위 정보를 통해 슬레이브는 현재 마스터가 기록한 마지막 로그 파일의 위치부터 복제하게 됩니다.
CHANGE MASTER TO // Master 연결정보 입력 명령어
MASTER_HOST='mysql-master', // 마스터 호스트명 또는 IP
MASTER_USER='replica_user', // 마스터 디비 접근 계정명
MASTER_PASSWORD='replica_pass', // 마스터 디비 접근 비밀번호
MASTER_LOG_FILE='mysql-bin.000003', // 마스터 디비 바이너리 파일명
MASTER_LOG_POS= 843; // 마스터 디비 바이너리 파일 Position
START SLAVE; // SLAVE 프로세스 시작
docker exec -it mysql-slave1 mysql -u root -p Slave1 DB 컨테이너로 접속후 CHANGE MASTER TO 명령어를 통해 Master 연결정보를 입력하고 START SLAVE 명령어를 통해 SLAVE 프로세스를 실행시켜 줍니다. SHOW MASTER STATUS; 명령어를 통해 Master DB와 연결에 이상이 없는지 확인할 수 있습니다. Slave2 DB에도 똑같은 작업을 진행해 줍니다.

이후 다시 Master Db 컨테이너로 접속후 board Database에 board 테이블을 생성후 데이터를 insert 해줍니다.


이후 Slave1, Slave2 디비로 접근후 board Database에 존재하는 board 테이블을 조회하면 Master Db에 insert한 데이터가 동일하게 복제되어있는걸 확인하실 수 있습니다.
Spring Framework에서 Transaction 어노테이션을 사용할때 read-only속성에 따라 true일때는 Slave로 false일때는 Master로 쿼리 질의를 하도록 설정하여 부하분산에 활용할 수 있습니다.
오늘은 간단하게 MySql을 통해 Replication을 구성해보았습니다. AWS환경에서 많이 구현했었는데 직접 온프레미스 환경에 구축해보는 경험이 깊이를 더해주는거 같습니다. 혹시나 제가 놓치거나 잘못 사용한 설정값들이 있으면 코멘트 남겨주시면 감사하겠습니다. 그럼 이만..
추후 Master 장애시 어떻게 Slave를 Master로 승격시키는 페일오버를 할 수 있는지 알아봐야겠습니다.
'Infra' 카테고리의 다른 글
Private Docker Registre 구축 (0) | 2025.01.08 |
---|