[MySQL] Master-Slave 구축

오형상·2023년 8월 26일
0

RecipeFriend

목록 보기
7/8
post-thumbnail

MySQL 데이터 분산 처리를 위한 Master-Slave 이중화 구축

이중화를 하는 이유

데이터베이스의 트랜잭션을 readOnly로 셋팅할경우 성능이 상승하는 이점을 누릴 수 있습니다.
데이터베이스에서 일어나는 작업을 읽기와 쓰기로 나눈다면 대부분의 작업은 읽기에 해당한다고 볼 수 있습니다.

애플리케이션의 성능을 향상시키려고 할 때 쿼리를 튜닝한다면 조회 쿼리를 튜닝해 성능상의 이점을 얻는 경우가 굉장히 많습니다. 확장성 측면에서도 Master DB는 쓰기 작업만 담당하고 하위에 여러 Slave DB를 둘 수 있도록 구성하였습니다.

이중화를 구성하기 위해서는 현재 MySQL을 사용중이기 때문에 MySQL Replication에 대해서 알고 있어야 합니다.

MySQL Replication 이란?

말 그대로 Replication은 '복제'라는 뜻을 가지고 있습니다.
MySQL의 Master 서버의 데이터를 n개의 Slave 서버와 동기화 시켜주는 기능입니다. MySQL의 데이터를 실시간으로 백업하거나, DB 서버의 부하를 분산하기 위하여 사용합니다.

MySQL Replication의 동작 방식

  1. Master 데이터베이스가 binary log를 만들어 이벤트를 기록합니다.
  2. 각 Slave 데이터베이스는 어떤 이벤트까지 저장되어 있는지 기억하고 있습니다.
  3. Slave 데이터베이스의 IO Thread를 통해서 Master 데이터베이스에 이벤트를 요청하고 받아옵니다.
  4. Master 데이터베이스는 이벤트를 요청받으면 binlog dump thread를 통해서 클라이언트에게 이벤트를 전송합니다.
  5. IO thread는 전송받은 덤프 로그를 이용하여 relay log를 만듭니다.
    SQL thread는 relay log를 읽어서 이벤트를 다시 실행하여 Slave 데이터베이스에 데이터를 복사합니다.
  6. Replication은 Master 데이터베이스에 데이터를 insert 했을때 뿐만 아니라, 테이블을 생성하거나 테이블의 구조를 변경하였을때도 이벤트가 동작하여 Slave 데이터베이스에도 반영이됩니다.

환경 설정하기

시간이 없는 분들은 https://github.com/ohy1023/Shell-Script에서 shopping-mall-project 부분을 사용하시면 됩니다.

1. docker-compose.yml

docker-compose로 CI/CD하기 여기서 사용했던 docker-compose에 MYSQL 아래와 같이 부분을 수정하였습니다.

version: '3.8'

services:
  master:
    # 마스터 데이터베이스 컨테이너 설정
    build:
      context: ./
      dockerfile: master/Dockerfile
    restart: always
    environment:
      MYSQL_DATABASE: shoppingmall
      MYSQL_USER: user
      MYSQL_PASSWORD: 1234
      MYSQL_ROOT_PASSWORD: 1234
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    ports:
      - 3306:3306
    container_name: master
    volumes:
      - my-db-master:/var/lib/mysql
      - my-db-master:/var/lib/mysql-files
    networks:
      - mynet

  slave:
    # 슬레이브 데이터베이스 컨테이너 설정
    build:
      context: ./
      dockerfile: slave/Dockerfile
    restart: always
    environment:
      MYSQL_DATABASE: shoppingmall
      MYSQL_USER: user
      MYSQL_PASSWORD: 1234
      MYSQL_ROOT_PASSWORD: 1234
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    ports:
      - 3307:3306
    container_name: slave
    volumes:
      - my-db-slave:/var/lib/mysql
      - my-db-slave:/var/lib/mysql-files
    networks:
      - mynet
  redis:
    # Redis 컨테이너 설정
    container_name: redis
    image: redis
    ports:
      - 6379:6379
    restart: always
    networks:
      - mynet

  cache:
    # Redis 캐시 컨테이너 설정
    container_name: redis-cache
    image: redis
    ports:
      - 6480:6379
    restart: always
    networks:
      - mynet

  backend:
    # 백엔드 서비스 컨테이너 설정
    container_name: backend
    image: zvyg1023/shopping-mall
    expose:
      - 8080
    ports:
      - 8080:8080
    restart: always
    depends_on:
      - master
      - slave
      - redis
      - cache
    networks:
      - mynet

volumes:
  my-db-master:
  my-db-slave:

networks:
  mynet:
    driver: bridge

2. Master DB 환경 설정

Dockerfile 작성

각자 상황에 맞는 버전을 사용하시면 됩니다.
ex) FROM mysql:5.7

FROM mysql:8.0.33
# 호스트 머신의 ./master/my.cnf 파일을 새로운 이미지의 /etc/mysql/my.cnf 경로로 추가한다.
ADD ./master/my.cnf /etc/mysql/my.cnf

my.cnf 작성

[client]
# 클라이언트의 기본 문자 집합을 utf8mb4로 설정합니다.
default-character-set = utf8mb4

[mysql]
# MySQL의 기본 문자 집합을 utf8mb4로 설정합니다.
default-character-set = utf8mb4

# MySQL 서버(daemon) 설정 부분입니다.

[mysqld]
# MySQL 서버의 문자 집합을 utf8mb4로 설정합니다.
character-set-server = utf8mb4

# MySQL 서버의 정렬을 utf8mb4_unicode_ci로 설정합니다.
collation-server = utf8mb4_unicode_ci

# 서버의 기본 시간대를 GMT+9로 설정합니다.
default-time-zone = '+9:00'

# 이진 로그를 사용하여 MySQL 서버에서 발생한 변경 사항을 기록합니다. mysql-bin은 이진 로그 파일의 이름을 지정합니다.
log-bin = mysql-bin

# MySQL 서버의 고유한 식별자를 설정합니다. 이 식별자는 MySQL 복제(replication) 설정에서 사용됩니다.
server-id = 1

# MySQL 사용자의 인증 플러그인을 mysql_native_password로 지정합니다. 이는 5.7 버전 이전과의 호환성을 유지하기 위한 매커니즘입니다.
authentication_policy=mysql_native_password 

3. Slave DB 환경 설정

Dockerfile 작성

FROM mysql:8.0.33
ADD ./slave/my.cnf /etc/mysql/my.cnf

my.cnf 작성

[client]
# MySQL 클라이언트의 기본 문자 집합을 utf8mb4로 설정합니다.
default-character-set = utf8mb4

[mysql]
# MySQL의 기본 문자 집합을 utf8mb4로 설정합니다.
default-character-set = utf8mb4

[mysqld]
# MySQL 서버의 문자 집합을 utf8mb4로 설정합니다.
character-set-server = utf8mb4

# MySQL 서버의 정렬을 utf8mb4_unicode_ci로 설정합니다.
collation-server = utf8mb4_unicode_ci

# 서버의 기본 시간대를 GMT+9로 설정합니다.
default-time-zone = '+9:00'

# 복제를 위해 바이너리 로깅을 활성화합니다.
log_bin = mysql-bin

# 복제를 위한 서버 식별자를 설정합니다.
server_id = 2

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

# 슬레이브 서버에서 변경 사항을 이진 로그에 기록하도록 합니다.
log_replica_updates = ON

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

# 기본 인증 플러그인을 mysql_native_password로 설정합니다.
authentication_policy = mysql_native_password

4. docker-compose 실행

아래의 명령어로 docker-compose 실행 후

docker-compose up -d

docker ps 입력시 아래와 같이 나온다면 성공!

MySQL Replication 설정

1. Master - Slave 간의 통신을 위한 내부 IP 주소 확인하기

docker network ls 명령어로 도커 컨테이너의 네트워크 목록을 확인합니다.

현재 MySQL에서 사용하는 network의 이름은 root_mynet 입니다. Master의 IPv4Address가 필요하므로, 조회하도록 하겠습니다.

docker inspect <bridge의 network ID> 명령어를 입력하면 아래의 화면이 출력됩니다.

이중에서 필요한 정보는 master-db의 IPv4Address 입니다.
이 IPv4Address를 슬래시( / ) 이전까지 복사합니다.
여기서는 172.18.0.6/16 이므로 172.18.0.6 까지만 사용합니다.

이 IP 주소는 Slave 데이터베이스를 설정할때 필요한 정보이기 때문에 잘 기록해두시면 되겠습니다.

2. Master 설정

Master DB에 접속해서 설정을 해보겠습니다.

// Master 계정에 접속하기 위해 명령어 입력
docker exec -it master bash
// mysql을 root 계정으로 접속
mysql -u root -p

이 명령어를 입력하면 비밀번호를 입력하라는 멘트가 나오는데, 비밀번호를 입력하면 접속이됩니다.
Slave 설정을 위해 master 에서는 특정 정보만 가져오면 됩니다.

아래의 명령어를 콘솔에 입력해줍니다.

show master status;

File(mysql-bin.000007)과 Position(337) 값을 잘 기록해둡니다.

3. Slave 설정

이제 Slave 계정에 접속해서 Slave 설정을 해보겠습니다.
접속중인 Master DB에서 나가서 다시 터미널로 이동합니다.

// Slave 계정에 접속하기 위해 명령어 입력
docker exec -it slave bash
// mysql을 root 계정으로 접속
mysql -u root -p

Master와 같은 방법으로 접속되었습니다.

Slave 설정을 위해 아래와 같은 명령어를 입력해줍니다.

CHANGE MASTER TO MASTER_HOST='{master-db의 네트워크 IP}',
MASTER_USER='root',
MASTER_PASSWORD='{root 계정의 비밀번호}',
MASTER_LOG_FILE='{master-db의 바이너리 파일 이름}',
MASTER_LOG_POS={master-db에서 조회한 파일 포지션};

실행이 완료되면 slave를 아래의 명령어를 이용해 실행해줍니다.

start slave;

아래의 명령어를 입력해, 현재 replication 설정이 잘 되어있는지 확인합니다

show slave status\G;

많은 정보들이 출력되지만 여기서 봐야할 것은 딱 두가지 정보입니다.
Slave_IO_Running & Slave_SQL_Running 입니다. 이 두가지가 YES라면 현재 설정이 잘 되어있는 것입니다.

Refererce

0개의 댓글