데이터베이스의 트랜잭션을 readOnly로 셋팅할경우 성능이 상승하는 이점을 누릴 수 있습니다.
데이터베이스에서 일어나는 작업을 읽기와 쓰기로 나눈다면 대부분의 작업은 읽기에 해당한다고 볼 수 있습니다.
애플리케이션의 성능을 향상시키려고 할 때 쿼리를 튜닝한다면 조회 쿼리를 튜닝해 성능상의 이점을 얻는 경우가 굉장히 많습니다. 확장성 측면에서도 Master DB는 쓰기 작업만 담당하고 하위에 여러 Slave DB를 둘 수 있도록 구성하였습니다.
이중화를 구성하기 위해서는 현재 MySQL을 사용중이기 때문에 MySQL Replication에 대해서 알고 있어야 합니다.
말 그대로 Replication은 '복제'라는 뜻을 가지고 있습니다.
MySQL의 Master 서버의 데이터를 n개의 Slave 서버와 동기화 시켜주는 기능입니다. MySQL의 데이터를 실시간으로 백업하거나, DB 서버의 부하를 분산하기 위하여 사용합니다.
시간이 없는 분들은 https://github.com/ohy1023/Shell-Script에서 shopping-mall-project 부분을 사용하시면 됩니다.
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
각자 상황에 맞는 버전을 사용하시면 됩니다.
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
[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
FROM mysql:8.0.33
ADD ./slave/my.cnf /etc/mysql/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
아래의 명령어로 docker-compose 실행 후
docker-compose up -d
docker ps 입력시 아래와 같이 나온다면 성공!
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 데이터베이스를 설정할때 필요한 정보이기 때문에 잘 기록해두시면 되겠습니다.
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) 값을 잘 기록해둡니다.
이제 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
- https://inkyu-yoon.github.io/docs/Learned/DataBase/mysql-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
- https://dev.mysql.com/doc/refman/8.0/en/mysql-cluster-replication.html