[Tistory] Docker를 이용한 DB Replication 적용

원글 페이지 : 바로가기

DB Replication 2개 이상의 DB를 두어 DB의 부하를 분산시키는 기술로 보통 Master/Slave로 나누어 Insert, Update, Delete 처리는 Master DB에서 수행하고
Select 작업은 Slave DB에서 처리하도록 구성한다

Master DB는 데이터의 일관성을 보장해야하므로 Master DB에서 쓰기작업을 처리하게 되고,
Slave DB는 Master DB를 복제하여 read 작업을 수행, 일반적으로 웹페이지에서 읽기작업이 훨씬 많으므로 Slave DB를 다수 사용하는 경우가 많다

Slave DB는 Master DB에서 수행된 쓰기작업을 Binary로그를 통해 Master DB와 데이터를 동기화 한다
(Binary로그를 불러와 Master DB에서 실행된 이벤트를 동일하게 실행함)

프로젝트 진행중 AWS AuroraDB를 통해서 간단하게 읽기용 DB를 복제 할 수 있었으나,
Local에서의 DB Replication은 Docker를 통해서 진행 해보았다 설정파일 Docker를 이용해서 DB Replication을 적용 할 때 필요한 파일들은 아래와 같다

1. 아래 두개의 DockerFile을 실행 하기위한 DockerCompose
-2,3번의 Docker File을 실행해서 DockerImage를 생성하고 DockerContainer를 띄울때의 설정값이 저장되어있음

2. Master DB의 DockerImage를 생성하기 위한 DockerFile
3. Slaver DB의 DockerImage를 생성하기 위한 DockerFile
-DockerImage를 생성하고 DockerContainer가 실행되면 my.cnf 파일을 변경한다

4. Master DB를 DockerContainer로 실행 후 mysql 설정을 변경할 my.cnf 파일
5. Slaver DB를 DockerContainer로 실행 후 mysql 설정을 변경할 my.cnf 파일
-두 파일다 바이너리 로그를 활성화 하고 Slave에서는 읽기전용과 중계로그 저장위치를 설정해준다

[파일위치]
docker
├ docker-compose.yml
├ main
│ └ Dockerfile
│ └ my.cnf
└ replica
└ Dockerfile
└ my.cnf 더보기 ### docker-compose.yml

version: “1”
services:
# main 데이터베이스 서비스 정의
db-main:
# Dockerfile을 사용하여 이미지 빌드
build:
context: ./
dockerfile: main/Dockerfile
# 컨테이너 재시작 설정
restart: always
# 플랫폼 설정
platform: linux/x86_64
# 환경 변수 설정
environment:
MYSQL_DATABASE: ‘db’
MYSQL_USER: ‘user’
MYSQL_PASSWORD: ‘1234’
MYSQL_ROOT_PASSWORD: ‘1234’
# MySQL 서버 설정
command:
– –character-set-server=utf8mb4
– –collation-server=utf8mb4_unicode_ci
# 포트 포워딩 설정
ports:
– ‘3307:3306’
# 컨테이너 이름 설정
container_name: main-db
# 볼륨 설정
volumes:
– my-db-main:/var/lib/mysql
– my-db-main:/var/lib/mysql-files
# 네트워크 설정
networks:
– net-mysql

# replica 데이터베이스 서비스 정의
db-replica:
# Dockerfile을 사용하여 이미지 빌드
build:
context: ./
dockerfile: replica/Dockerfile
# 컨테이너 재시작 설정
restart: always
# 플랫폼 설정
platform: linux/x86_64
# 환경 변수 설정
environment:
MYSQL_DATABASE: ‘db’
MYSQL_USER: ‘user’
MYSQL_PASSWORD: ‘1234’
MYSQL_ROOT_PASSWORD: ‘1234’
# MySQL 서버 설정
command:
– –character-set-server=utf8mb4
– –collation-server=utf8mb4_unicode_ci
# 포트 포워딩 설정
ports:
– ‘3308:3306′
# 컨테이너 이름 설정
container_name: replica-db
# 볼륨 설정
volumes:
– my-db-replica:/var/lib/mysql
– my-db-replica:/var/lib/mysql-files
# 네트워크 설정
networks:
– net-mysql

# 볼륨 설정
volumes:
my-db-main:
my-db-replica:

# 네트워크 설정
networks:
net-mysql:
driver: bridge ### main/Dockerfile

# MySQL 8.0 이미지를 기반으로 함
FROM mysql:8.0
# 로컬 파일 시스템에서 main 디렉토리에 있는 my.cnf 파일을 컨테이너 내부의 /etc/mysql/my.cnf 경로로 복사함
ADD ./main/my.cnf /etc/mysql/my.cnf ### main/my.cnf

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-time-zone=’+9:00′

# 바이너리 로그 활성화
log-bin = mysql-bin

# 서버 식별 ID 설정
server-id = 1

# 기본 인증 플러그인 설정
default_authentication_plugin=mysql_native_password ### replica/Dockerfile

# MySQL 8.0 이미지를 기반으로 함
FROM mysql:8.0
# 로컬 파일 시스템에서 replica 디렉토리에 있는 my.cnf 파일을 컨테이너 내부의 /etc/mysql/my.cnf 경로로 복사함
ADD ./replica/my.cnf /etc/mysql/my.cnf ### replica/my.cnf

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-time-zone=’+9:00’

# 바이너리 로그 활성화
log_bin = mysql-bin
# 서버 식별 ID 설정
server_id = 2

# MySQL 슬레이브 서버에서 사용되는 중계 로그의 저장 위치를 지정합니다.
relay_log = /var/lib/mysql/mysql-relay-bin

# 이 설정은 슬레이브 서버에서 발행된 변경 사항도 바이너리 로그에 기록하도록 허용합니다.
# 기본적으로, 슬레이브 서버에서 변경 사항은 바이너리 로그에 기록되지 않습니다.
log_slave_updates = 1

# 슬레이브 서버를 읽기 전용 모드로 설정합니다.
read_only = 1

# 기본 인증 플러그인 설정
default_authentication_plugin = mysql_native_password DockerCompose 실행 docker-compose.yml 파일 경로에서 아래 명령어로 실행이 가능하며
$ docker-compose up -d
프로젝트 내에 파일이 위치 할 경우 IntelliJ에서도 실행이 가능하다 실행하면 Docker내에 Images와 Containers에 아래와 같이 생성되어있다 DockerImage DockerContainer Replicaion 설정 이제 Replicaion 설정을 해야한다
Master DB가 사용하고있는 ip와 Binary로그 파일명, 파일 포지션이 필요하다 $ docker network ls
현재 Container에서 사용하는 네트워크 ID를 확인해서
$ docker inspect
main-db에서 사용하는 IP를 확인해준다

**Docker Desktop을 사용하고 있으면 간단하게 main-db의 Inspect에서 ctrl + f로 ip로 검색이 가능하다 이제 Master DB에 접근해서 Binary로그 파일명과 파일 포지션를 찾는다

아래 이미지처럼 main-db Container로 접근해서 mysql 로그인 후 아래 명령어로 파일과 포지션을 확인한다
mysql> show master status;

**이부분도 DockerDesktop을 사용하면 Exec탭에서도 가능하다 이제 Slave DB에 Master DB의 Binary로그 파일명, 포지션등을 설정해줘야 한다

Master와 동일하게 replica-db Container로 접근해서 mysql 로그인 Master DB의 설정값을 저장한다
mysql> CHANGE MASTER TO MASTER_HOST='{master-db의 네트워크 IP}’,
MASTER_USER=’root’,
MASTER_PASSWORD='{root 계정의 비밀번호}’,
MASTER_LOG_FILE='{master-db의 바이너리 파일 이름}’,
MASTER_LOG_POS={master-db에서 조회한 파일 포지션};

**이부분도 DockerDesktop을 사용하면 Exec탭에서도 가능하다
**나의 경우는 입력하는 값이 아래와 같았다
CHANGE MASTER TO MASTER_HOST=’172.18.0.2′,
MASTER_USER=’root’,
MASTER_PASSWORD=’1234′,
MASTER_LOG_FILE=’mysql-bin.000012′,
MASTER_LOG_POS=157; 설정이 완료되면 slaver를 아래 명령어로 실행한다
mysql> start slave;

설정이 되었는지는 아래 명령어로 확인하며 Slave_IO_Running & Slave_SQL_Running: Yes로 되어있으면 성공이다
mysql> show slave status\G; 테스트 현재 프로젝트에서는 @Transaction 이면 Master DB, readOnly가 붙어있으면 Slave DB를 타도록 설정되어 있다 정상적으로 log.info로 찍어놓은 main, replica가 찍히는걸 확인 할 수 있다
또한 두 DB에 입력되어있는 값도 동일한것이 확인 되었다 참고
*Local Replication 적용
https://velog.io/@ch4570/MySQL-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%82%B0-%EC%B2%98%EB%A6%AC%EB%A5%BC-%EC%9C%84%ED%95%9C-Master-Slave-%EC%9D%B4%EC%A4%91%ED%99%94%EB%A5%BC-%EA%B5%AC%EC%84%B1%ED%95%98%EB%8B%A4MySQL-Replication-%EC%84%A4%EC%A0%95%EA%B3%BC-%EA%B5%AC%EC%84%B1
*MySQL Binary로그 개념
https://myinfrabox.tistory.com/20

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다