NestJs에서의 Sequelize Master Slave

오병진·2022년 9월 27일
0

개념은 인터넷에 넘치고, 설정방법이 애매하게 올라온 것이 많아 이렇게 글을 올린다.
글의 피드백은 언제나 환영입니다.


위치가 다른 DB 두가지가 필요합니다!

필자는 다음과 같이 도커로 했습니다.

Master Slave 세팅

DB 기본 세팅

version: "2"
services:
  master_db:
    image: mysql:5.6
    command: mysqld --default-authentication-plugin=mysql_native_password
    container_name: local_master_db
    ports:
      - "3307:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: local_db
      MYSQL_USER: masteruser
      MYSQL_PASSWORD: 1q2w3e4r
      MYSQL_ROOT_HOST: "%"
    command: 
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      
  slave_db:
    image: mysql:5.6
    command: mysqld --default-authentication-plugin=mysql_native_password
    container_name: local_slave_db
    ports:
      - "3308:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: local_db
      MYSQL_USER: devuser
      MYSQL_PASSWORD: 1q2w3e4r
      MYSQL_ROOT_HOST: "%"
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci

DB my.cnf 세팅

그리고 각 DB의 /etc/mysql/my.cnf에다가 값을 추가해줘야한다.

Master

[mysqld]
log-bin=mysql-bin
server-id=1

Slave

[mysqld]
log-bin=mysql-bin
server-id=2

여기서 server-id 서버 구분값이니 안겹치게 원하는 것으로 넣어도 좋다.
설정이 끝난다면 service mysql restart를 통해 설정을 완료해주자

데이터 복제용 계정 생성

Slave서버에서 Master 서버로 접속할 계정이 필요하다.
Master서버에서 복제용 계정을 생성해보자

create user 'slave'@'%' identified by 'work_slave';
grant replication slave on *.* to 'slave'@'%';
flush privileges;

좋았다. 일 할 노예가 생겼다.

연결용 정보 확인

Slave서버에서 연결하기 위해선 Master서버의 정보가 필요하다.
Master서버에서 정보를 확인하자

show master status;

+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 |      120 | local_db     |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

다음과 같은 식이다.
FilePosition만 챙기자

Slave에서 연결하기

masterslave를 동기화하기 위해선 동기화가 되어있어야 한다.
동기화를 위해 dump를 해주자

mysqldump -u root -P 3307 -p {db_name} > C:Users\Sunrabbit\Desktop\nest\db.sql

mysql -u root -P 3308  -p {db_name} < C:\Users\Sunrabbit\Desktop\nest\db.sql

master 정보 입력

slave에서 master의 정보를 입력해주자

change master to
	master_host='localhost',
    master_user='slave',
    master_password='work_slave',
    master_log_file='mysql-bin.000004',
    master_log_pos=120, master_port=3307

다음 코드는 지극히 나의 상황에 맞는 코드다.
알아서 눈치껏 바꾸고 채워넣자

시작

slave에서 slave를 시작해보자

start slave

사후처리

대충 연결 안되는 이유는 Connect Error 라던지, 방화벽이라던지 클라이언트 접속 문제라던지 많다.
눈치껏 연결되는지 체크하고 해봐라.

show slave status\G

를 입력하면 여러 정보들을 보여준다
구글은 신이다.

만약 잘된다면 다음과 같은 Slave_Io_State가 나타난다.
물론 이건 Master에서 입력한거다.

MySQL [(none)]> show processlist;

+----+-------+------------------+------+-------------+------+-----------------------------------------------------------------------+------------------+
| Id | User  | Host             | db   | Command     | Time | State                                                                 | Info             |
+----+-------+------------------+------+-------------+------+-----------------------------------------------------------------------+------------------+
|  1 | slave | 192.168.0.1:50648 | NULL | Binlog Dump |   80 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL             |
|  2 | root  | 192.168.0.1:50652 | NULL | Query       |    0 | init                                                                  | show processlist |
+----+-------+------------------+------+-------------+------+-----------------------------------------------------------------------+------------------+

Slave에서라면 다음과 같은 식이다.

MySQL [(none)]> show processlist;

+----+-------------+------------------+-------+---------+------+-----------------------------------------------------------------------------+------------------+
| Id | User        | Host             | db    | Command | Time | State                                                                       | Info             |
+----+-------------+------------------+-------+---------+------+-----------------------------------------------------------------------------+------------------+
|  1 | system user |                  | NULL  | Connect |  274 | Waiting for master to send event                                            | NULL             |
|  2 | system user |                  | NULL  | Connect |  127 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL             |
|  4 | root        | 192.168.0.1:41820 | mysql | Query   |    0 | init                                                                        | show processlist |
+----+-------------+------------------+-------+---------+------+-----------------------------------------------------------------------------+------------------+

Nest에서 연결하기

대부분은 이거 보고 하면 된다.
공식문서 최고.
그 중 databaseProvider를 입력하는 부분이 좀 달라질뿐이다.

export const dbProviders = [
  {
    provide: "SEQUELIZE",
    useFactory: async () => {
      const sequelize = new Sequelize({
        dialect: "mysql",
        host: "localhost",
        database: "local_db",
        replication: {
          read: [
            {
              port: 3308,
              username: "devuser",
              password: "1q2w3e4r",
            },
          ],
          write: {
            username: "masteruser",
            password: "1q2w3e4r",
            port: 3307,
          },
        },
      });
      sequelize.addModels([entity.User]);
      await sequelize.sync();
      return sequelize;
    },
  },
];

다음처럼 replicationreadwrite만 구분해주면 된다.

profile
지나가는 사람입니다. 마저 지나갈게요 :D

0개의 댓글