본문 바로가기
DB

[MySQL] Replication 적용기 - 1

by 에드박 2021. 10. 22.

MySQL에 Replication을 적용하면서 학습한 내용을 정리하려고 합니다!

 

Replication의 사전적 의미는 복제 입니다.

(평소 자주 접했던 단어로 레플리카(replica)가 있는데 보통 옷의 복제품을 의미했습니다.)

 

그럼 Database에서 Replication은 무엇일까요?

하나의 데이터베이스 서버를 복제해서 하나 이상의 데이터베이스 서버로 복사하는 것을 의미합니다.

이때 복사의 주체를 소스(source) 서버 라고 합니다.

그리고 복사된 서버들을 복사본(replica) 서버 라고 합니다.

 

용어의 통일을 위해서 지금부터는 복사의 주체를 source 서버 복사된 서버를 replica 서버 라고 하겠습니다.

보통 master/slave 서버라고 불렀지만 2020년부터 해당 단어들이 변경되고 있습니다.
해당 용어들이 노예제도와 관련됐다고 논란이 되어 많은 곳에서 다른 용어로 대체하고 있습니다.
대표적으로 Github 의 기본 브랜치 이름이 master -> main 으로 바뀐것을 볼 수 있습니다.
위키피디아 Master/Slave(Technology)

 

복사는 비동기 방식으로 이뤄집니다. replica 서버는 실시간 업데이트를 수신하기 위해 source 서버와 영구적으로 연결될 필요가 없습니다.

구성에 따라 모든 데이터베이스, 선택한 데이터베이스, 데이터베이스 내의 테이블을 복사할 수 있습니다.

 


MySQL에서 Replication의 장점

  • Scale out solution
    • 성능을 향상시키기 위해 여러 replica 서버에 부하를 분산시킬 수 있습니다.
    • 모든 쓰기,수정,삭제 등의 업데이트 작업은 source 서버에서 이뤄져야 합니다.
    • 읽기는 하나 이상의 replica 서버에서 담당합니다.
    • 즉 업데이트(CUD), 조회(R)의 부하를 각각의 서버에 분산 시킴으로서 성능을 향상시킬 수 있습니다.
  • 데이터 보안
    • replica 서버는 replication을 일시 중지 할 수 있으므로 원본 데이터를 손상시키지 않고 replica 서버에서 백업 서비스를 실행할 수 있습니다.
  • 분석
    • 업데이트는 source 서버에서 이뤄지므로 데이터 분석에 대한 부하는 replica 서버에서만 일어나므로 서비스의 성능에 영향을 주지 않고 분석이 가능해집니다.
  • 장거리 데이터 배포
    • Replication을 사용해서 source 서버에 대한 영구 액세스 없이 원격 사이트에서 사용할 데이터의 로컬 복사본을 생성할 수 있습니다.

 


MySQL Replication 사전 설정

우선 Replication을 사용하도록 source 서버를 구성하려면 두 가지 설정을 확인해야 합니다.

  • 바이너리 로깅이 활성화 됐는가?
  • 고유한 서버 ID가 설정 됐는가?

바이너리 로깅이 활성화 됐는가?

mysql 서버에서 다음과 같은 명령어로 확인이 가능합니다.

show variables like '%log_bin%';

log_bin 의 value 가 ON으로 되있어야 바이너리 로깅이 활성화 된 상태입니다.

 

my.cnf를 통해서도 확인이 가능한데 MySQL의 경우는 기본적으로 활성화가 된 상태로 보입니다.

MariaDB의 경우 10.5버전 기준 기본적으로 비활성화 상태이니 확인하셔야 합니다!

 

아래는 mysql의 my.cnf에는 해당 설정이 명시되있지 않고 default로 설정이 ON 되있는 것으로 보입니다!

만약 꺼져있는 경우에는 아래와 같이 설정해주세요. my.cnf의 [mysqld] 설정에 해주시면 됩니다.

[mysqld]
log_bin = /var/log/mysql/binlog파일명.log
expire_logs_days = 10   # 바이너리 로그 만료 기간
max_binlog_size = 100M # 바이너리 로그의 최대 크기

 

고유한 서버 ID가 활성화 됐는가?

Replication 구성을 위해서는 source 서버와 replica 서버들의 server_id 가 달라야합니다. 즉, 각각의 서버는 고유해야합니다.

MySQL의 server_id는 기본값이 1이며 master 서버의 경우 기본값인 1을 유지해서 사용해도 됩니다.

(replica 서버에서 server_id를 다르게 설정할 수 있으니까요!)

 

해당 설정값을 확인하는 명령어

show variables like 'server_id';

 

server_id는 다음 명령어로 mysql-cli에서 동적으로 변경이 가능합니다.

SET GLOBAL server_id = 2

 

my.cnf 에서도 변경이 가능합니다.

[mysqld] 설정에 명시하시면 됩니다.

해당 설정값이 언더스코어('_')인지 하이픈('-') 인지는 MySQL의 버전에 따라 다릅니다.

최근 버전인 MySQL 8.0에서는 대부분의 환경변수 이름이 언더스코어('_')로 변경됐지만 이전에는 섞어서 사용했으므로 주의해야합니다!

즉 최신버전에서는 server_id 이지만 예전 버전에서는 server-id 일 수 있습니다.

[mysqld]
server_id = 1


Replication을 위한 유저 생성

각 replica 서버는 MySQL 사용자 이름과 비밀번호를 사용하여 source 서버에 연결하므로 replica 서버가 연결하는 데 사용할 수 있는 사용자 계정이 source 서버에 있어야 합니다.

사용자 이름은 replica 서버를 설정할 때 다음의 옵션에 의해 지정됩니다. (버전에 따라 명령어가 다릅니다.)

  • CHANGE Replication SOURCE TO(MySQL 8.0.23) 의 SOURCE_USER 옵션에 의해 지정
  • CHANGE MASTER TO(MySQL 8.0.23 이전 버전) 의 MASTER_USER 옵션에 의해 지정

위의 명령어는 Replication SLAVE 권한이 부여된 사용자 계정에 사용할 수 있습니다.

(말이 좀 어렵지만 아래 과정을 진행하면서 이해할 수 있을테니 이 문장에 너무 묶여있지 않으셔도 됩니다!)

 

각 replica 서버에 대해 다른 사용자 계정을 각각 만들거나 각 replica 서버에 대해 동일한 계정을 사용하여 원본에 연결할 수 있습니다.

master 서버의 Replication SLAVE 권한의 유저 1개 : N개의 replica 서버
master 서버의 Replication SLAVE 권한의 유저 N개 : N개의 replica 서버

 

Replication SLAVE 권한을 가진 유저 생성은 다음의 명령어로 생성할 수 있습니다.

mysql> CREATE USER 'replication_usesrname'@'%.example.com' IDENTIFIED BY 'password';

mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication_usesrname'@'%.example.com';

replication을 위해 특별히 계정을 생성할 필요는 없지만 복제 사용자 이름과 암호는 replica 서버의 연결 메타데이터 저장소에 일반 텍스트로 저장됩니다는 점에 유의해야 합니다. 따라서 다른 계정에 대한 손상 가능성을 최소화하기 위해 replication 프로세스에 대해서만 권한을 가지는 별도의 계정을 생성해서 진행할 수 있습니다.


replication source 서버 바이너리 로그 좌표값 얻기

replication 구성을 위해서는 replica 서버가 source 서버 바이너리 로그의 현재 마지막 좌표(로그의 가장 마지막 위치가 어디인지)를 알아야합니다. 그래야 replica 서버가 바이너리 로그의 현재 마지막 좌표를 기준으로 읽어서 업데이트를 할 수 있습니다.

 

1. 우선 source 서버의  모든 테이블과 블록에 쓰기 명령을 플러시해야합니다. 마지막 좌표를 읽었지만 데이터가 써지면 좌표가 변경되기 때문입니다. 또한 읽기 잠금을 겁니다.

mysql> FLUSH TABLES WITH READ LOCK;

2. source 서버에서 SHOW MASTER STATUS; 명령어로 현재 바이너리 로그 파일명과 좌표를 알아낼 수 있습니다.

출처 : mysql replication 문서 - https://dev.mysql.com/doc/refman/8.0/en/replication-howto-masterstatus.html

File 컬럼은 현재 바이너리 로그의 파일명입니다.

Position 컬럼은 현재 바이너리 로그 파일의 마지막 좌표를 의미합니다.

즉 여기서는 mysql-bin.000003 가 현재 바이너리 로그 파일이고 73이 현재 마지막 좌표입니다.

 


데이터 스냅샷

source 서버에 원래 데이터가 존재했던 경우에는 replica 서버에 해당 데이터를 복사해줘야 합니다.

source 데이터베이스에서 데이터를 덤프하는 여러가지 방법이 있습니다. 여기서는 InnoDB를 사용할 때 권장되는 방법인 mysqldump를 사용해서 데이터 스냅샷을 생성하겠습니다. (다양한 방법은 이 곳 을 참고해주세요!)

 

mysqldump를 사용해서 아래와 같이 모든 데이터베이스 덤프를 만들 수 있습니다.

MySQL 8.0.23 이전 : mysqldump -u root -p --all-databases --master-data > dbdump.sql
MySQL 8.0.23 : mysqldump -u root -p --all-databases --source-data > dbdump.sql

만들어진 백업 파일을 replica 서버에 적용합니다.

(아래 명령어는 replica 서버에서 진행합니다.)

mysql -u root -p < dbdump.sql

 

여기까지 진행했다면 아까 source 서버에 걸었던 읽기 잠금을 해제합니다.

mysql> UNLOCK TABLES;

replica 서버에서 source 서버 구성 설정

 

이제 replication을 위해 replica 서버와 source 서버가 통신할 수 있도록 replica 서버에 연결 정보를 설정해야 합니다.

 

위에서 한번 언급했듯 MySQL 버전에 따라 명령어가 달라질 수 있습니다.

  • CHANGE Replication SOURCE TO(MySQL 8.0.23) 의 SOURCE 옵션에 의해 지정
mysql> CHANGE REPLICATION SOURCE TO
> SOURCE_HOST='source_host_name',
> SOURCE_USER='replication_user_name',
> SOURCE_PASSWORD='replication_password',
> SOURCE_FILE='recorded_log_filename',
> SOURCE_LOG_POS=recorded_log_position;

ex.
mysql> CHANGE REPLICATION SOURCE TO
> SOURCE_HOST='172.17.0.1',
> SOURCE_USER='replication_usesrname',
> SOURCE_PASSWORD='password',
> SOURCE_FILE='mysql-bin.000002',
> SOURCE_LOG_POS=73;
  • CHANGE MASTER TO(MySQL 8.0.23 이전 버전) 의 MASTER 옵션에 의해 지정
mysql> CHANGE MASTER TO
> MASTER_HOST='source_host_name',
> MASTER_USER='replication_user_name',
> MASTER_PASSWORD='replication_password',
> MASTER_FILE='recorded_log_filename',
> MASTER_LOG_POS=recorded_log_position;

ex.
mysql> CHANGE MASTER TO
> MASTER_HOST='172.17.0.1',
> MASTER_USER='
replication_usesrname',
> MASTER_PASSWORD='password',
> MASTER_FILE='
mysql-bin.000002',
> MASTER_LOG_POS=73;

 

이제 replica 서버와 source 서버의 연결 설정을 완료했습니다.

아래의 명령어로 replica 환경을 실행합니다.

mysql> START SLAVE;

replica 서버의 실행 상태는 SHOW SLAVE STATUS; 명령어로 확인할 수 있습니다.

mysql> SHOW SLAVE STATUS;

Slave_IO_Running, Slave_SQL_Running 의 값이 Yes라면 성공적으로 구축된것입니다.

 

 

다음글에서는 해당 replication 환경을 사용해서 Spring 프로젝트에 DB Scale out 을 적용해보겠습니다.


참고자료

- MySQL replication 문서

- Spring 레플리케이션 트랜잭션 처리 방식 - Yun Blog

- Spring 동일한 Bean(Class)에서 @Transactional 동작 방식 - Yun Blog

댓글