[replication] mysql Replication ์œผ๋กœ DB ๋ถ€ํ•˜ ๋ถ„์‚ฐ ์‹œํ‚ค๊ธฐ

Mysql์˜ Replicatoin ๊ฐœ๋…์„ ์ •๋ฆฌํ•˜๊ณ  ํ”„๋กœ์ ํŠธ ์ค‘ AI ๋ชจ๋ธ ์žฌํ•™์Šต ์‹œ 900๋งŒ ๊ฑด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋ฉด์„œ ์ƒ๊ธฐ๋Š” DB์˜ ๋ถ€ํ•˜๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•œ ํฌ์Šคํ„ฐ์ž…๋‹ˆ๋‹ค. 

 

 

 

 

1. ๋ณต์ œ(Replication)

๋ณต์ œ(Replication)๋Š” 1๊ฐœ ์ด์ƒ์˜ ๋ ˆํ”Œ๋ฆฌ์นด(replica) ์ €์žฅ์†Œ๊ฐ€ ์†Œ์Šค ์ €์žฅ์†Œ์™€ ๋™๊ธฐํ™”๋ฅผ ์ž๋™์œผ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ณผ์ •์ด๋‹ค. ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ตœ์†Œ ๊ตฌ์„ฑ์€ Master / Slave์ด๋‹ค.

 

Master DBMS ์—ญํ• 

์›น์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ๋“ฑ๋ก/์ˆ˜์ •/์‚ญ์ œ ์š”์ฒญ์‹œ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ๊ทธ(Binarylog)๋ฅผ ์ƒ์„ฑํ•˜์—ฌ Slave ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค. (์›น์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ์š”์ฒญํ•œ ๋ฐ์ดํ„ฐ ๋“ฑ๋ก/์ˆ˜์ •/์‚ญ์ œ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” DBMS๋กœ ๋งŽ์ด ์‚ฌ์šฉ)

 

Slave DBMS ์—ญํ• 

Master DBMS๋กœ ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ๊ทธ(Binarylog)๋ฅผ ๋ฐ์ดํ„ฐ๋กœ ๋ฐ˜์˜ํ•˜๊ฒŒ ๋œ๋‹ค. (์›น์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ์š”์ฒญ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” DBMS๋กœ ๋งŽ์ด ์‚ฌ์šฉ)

 

 

 

 

 

 

 

 

 

 

2. Mysql Repication ์‚ฌ์šฉ ๋ชฉ์ 

mysql ๋ฆฌํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‚ฌ์šฉ๋ชฉ์ ์€ ํฌ๊ฒŒ ์‹ค์‹œ๊ฐ„ Data ๋ฐฑ์—…๊ณผ ์—ฌ๋Ÿฌ๋Œ€์˜ DB ์„œ๋ฒ„์˜ ๋ถ€ํ•˜๋ฅผ ๋ถ„์‚ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. 

 

๋จผ์ € ๋ฐ์ดํ„ฐ์˜ ๋ฐฑ์—…์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด Master ์„œ๋ฒ„๋ฅผ ๋ฐ์ดํ„ฐ์˜ ์›๋ณธ์„œ๋ฒ„, Slave ์„œ๋ฒ„๋ฅผ ๋ฐฑ์—… ์„œ๋ฒ„๋กœ ์ง€์นญํ•˜์˜€๋‹ค.

Master ์„œ๋ฒ„์— DBMS์˜ ๋“ฑ๋ก/์ˆ˜์ •/์—…๋ฐ์ดํŠธ๊ฐ€ ์ƒ๊ธฐ๋Š” ์ฆ‰์‹œ Slave ์„œ๋ฒ„์˜ ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋Ÿฌํ•œ ๊ณผ์ •์œผ๋กœ ๋ฐฑ์—…์„ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Master ์„œ๋ฒ„์˜ ์žฅ์• ๊ฐ€ ์ƒ๊ฒผ์„ ๊ฒฝ์šฐ Slave ์„œ๋ฒ„๋ฅผ DB๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

DBMS์˜ ๋ถ€ํ•˜ ๋ถ„์‚ฐ์ด๋‹ค.

์‚ฌ์šฉ์ž์˜ ํญ์ฃผ๋กœ ์ธํ•ด 1๋Œ€์˜ DB์„œ๋ฒ„๋กœ ๊ฐ๋‹นํ•  ์ˆ˜ ์—†์„ ๋•Œ, MySQL ๋ ˆํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ด์šฉํ•˜์—ฌ ๊ฐ™์€ DB ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ๋Œ€๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€ํ•˜๋ฅผ ๋ถ„์‚ฐ์‹œ์ผœ์ค„ ์ˆ˜ ์žˆ๋‹ค. 

์œ„์—์„œ๋„ ์–˜๊ธฐํ–ˆ๋“ฏ์ด Master ์„œ๋ฒ„๋Š” ๋“ฑ๋ก/์ˆ˜์ •/์‚ญ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋ฒ„๋กœ ์‚ฌ์šฉํ•˜๊ณ , Slave ์„œ๋ฒ„๋Š” ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ ๋ถ€ํ•˜๋ฅผ ๋ถ„์‚ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. 

 

 

์ด ์™ธ์—๋„ ๋ณต์ œ์˜ ์žฅ์ ๋“ค์—” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ๋“ค์ด ์žˆ๋‹ค. 

 

  • ๋ถ„์„
    • ์›๋ณธ ๋ฐ์ดํ„ฐ์— ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ์›๋ณธ ๋ฐ์ดํ„ฐ์— ์„ฑ๋Šฅ ์ด์Šˆ์—†์ด ๋ ˆํ”Œ๋ฆฌ์นด์—์„œ ๋ถ„์„์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์›๊ฑฐ๋ฆฌ ๋ฐ์ดํ„ฐ ๋ถ„์‚ฐ
    • ์›๋ณธ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜์ง€ ์•Š๊ณ ๋„,  ์›๊ฒฉ ์‚ฌ์ดํŠธ์—์„œ ์‚ฌ์šฉ ํ•  ๋กœ์ปฌ ๋ฐ์ดํ„ฐ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

 

 

3. ๋ณต์ œ์˜ ์›๋ฆฌ

์•„๋ž˜๋Š” MySQL์˜ Master-Slave ๋ณต์ œ ์›๋ฆฌ์ด๋‹ค.

 

MySQL์—์„œ ๋ณต์ œ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ๋กœ๊ทธ ํŒŒ์ผ์— ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋ชจ๋“  ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๊ธฐ๋กํ•œ๋‹ค.

1. ๋ ˆํ”Œ๋ฆฌ์นด๊ฐ€ ์ดˆ๊ธฐํ™”๊ฐ€ ๋œ๋‹ค๋ฉด, 2๊ฐœ์˜ ์“ฐ๋ ˆ๋“œ ์ž‘์—…์„ ์ƒ์„ฑ

2. ํ•˜๋‚˜๋Š” I/O ์“ฐ๋ ˆ๋“œ๋กœ ์›๋ณธ ์ธ์Šคํ„ด์Šค์— ์—ฐ๊ฒฐํ•˜๊ณ  ํ•œ ์ค„์”ฉ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋กœ๊ทธ๋ฅผ ์ฝ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ ˆํ”Œ๋ฆฌ์นด ์„œ๋ฒ„์˜ Relay ๋กœ๊ทธ์— ํ•ด๋‹น ๋‚ด์šฉ๋“ค์„ ๋ณต์‚ฌ.

3. ๋‘๋ฒˆ์งธ ์“ฐ๋ ˆ๋“œ๋Š” SQL ์“ฐ๋ ˆ๋“œ๋กœ, relay ๋กœ๊ทธ๋ฅผ ์ฝ๊ณ  ๋ ˆํ”Œ๋ฆฌ์นด ์ธ์Šคํ„ด์Šค์— ์ตœ๋Œ€ํ•œ ๋น ๋ฅด๊ฒŒ ์ ์šฉ๋‹ค.

 

 

 

 

 

 

 

 

 

4. Replication ์ „ ์ฃผ์˜ ์‚ฌํ•ญ

mysql replication์„ ์ง„ํ–‰ํ•˜๊ธฐ ์ „ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฃผ์˜ํ•ด์•ผ ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ๋“ค์ด ์žˆ๋‹ค.

 

1. ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด Replication์„ ์‚ฌ์šฉํ•˜๋Š” MySQL์˜ ๋ฒ„์ „์€ ๋™์ผํ•˜๊ฒŒ ๋งž์ถ”๊ธฐ

2. Replication์„ ์‚ฌ์šฉํ•˜๊ธฐ์— MySQL ๋ฒ„์ „์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ Slave ์„œ๋ฒ„๊ฐ€ ์ƒ์œ„ ๋ฒ„์ „์ด์–ด์•ผ ํ•œ๋‹ค.

3. Replication์„ ๊ฐ€๋™์‹œ์— Master ์„œ๋ฒ„, Slave ์„œ๋ฒ„ ์ˆœ์œผ๋กœ ๊ฐ€๋™์‹œ์ผœ์•ผ ํ•œ๋‹ค.

 

 

 

 

 

 

 

 

5. ๊ตฌ์„ฑํ•ด๋ณด๊ธฐ

๋‘ ๊ฐœ์˜ ์šฐ๋ถ„ํˆฌ ํ™˜๊ฒฝ์—์„œ ํ•ด๋ณด๋ ค๋‹ค ๊ฐ„๋‹จํ•˜๊ฒŒ Docker๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌ์„ฑํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

 

5-1. master DB ์ƒ์„ฑ

master ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰ ํ›„ ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ ์ ‘์†, ์„ค์ • ํŒŒ์ผ ์ˆ˜์ •์„ ์œ„ํ•ด vim ์„ค์น˜

vim ์„ค์น˜๊ฐ€ ์•ˆ ๋  ๊ฒฝ์šฐ, ๋กœ์ปฌ์—์„œ my.cnf๋ฅผ ์ƒ์„ฑํ•ด docker cp๋กœ ๋„ฃ์–ด์ฃผ์ž. ์ด๋ฏธ์ง€ ๋งˆ๋‹ค apt๋ฅผ ์ง€์›ํ•ด์ฃผ๋Š” ์ด๋ฏธ์ง€๋„ ์žˆ๊ณ  ์•„๋‹Œ ๊ฒƒ๋„ ์žˆ๋‹ค. 

$ docker run -p 3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=1234 -d mysql:8-debian

$ docker exec -it mysql-master /bin/bash

$ apt-get update
$ apt-get install -y vim

 

vi ๋ช…๋ น์–ด๋กœ /etc/mysql/my.cnf ํŒŒ์ผ์„ ์—ด๊ณ , ์•„๋ž˜์™€ ๊ฐ™์ด 2์ค„์„ ์ถ”๊ฐ€

log-bin=mysql-bin  
server-id=1

 

 

๊ธฐ์กด ์šด์˜์ค‘์ธ DB๋ฅผ Replicationํ•  ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฑ์—…ํ•ด์•ผ ํ•˜๋Š”๋ฐ ์ด๋•Œ ๋ณดํ†ต dump๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค. dump์‹œ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์˜ฌ๋ ค์ฃผ๋ ค๋ฉด buffer size๋ฅผ ๋Š˜๋ ค ์ง„ํ–‰ํ•˜๋ฉด ๋œ๋‹ค. 

์•„๋ž˜๋Š” dummy data๋ฅผ ๋„ฃ์—ˆ์ง€๋งŒ ์ถ”ํ›„์— ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์…‹์„ insertํ•ด์•ผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜ ์˜ต์…˜๋„ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค. 

innodb_buffer_pool_size = 4G
innodb_log_file_size = 1G

 

 

ํ˜„์žฌ ์‚ฌ์šฉ์ค‘์ธ ๋ฒ„ํผ ์‚ฌ์ด์ฆˆ๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ mysql์— ์ž…๋ ฅํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

SHOW VARIABLES LIKE 'innodb_buffer_pool_size';

 

 

log bin

์—…๋ฐ์ดํŠธ๋˜๋Š” ๋ชจ๋“  ์ฟผ๋ฆฌ๋“ค์ด Binary log ํŒŒ์ผ์— ๊ธฐ๋ก๋œ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ Binary log ํŒŒ์ผ์€ MySQL์˜ data directory์ธ /var/lib/mysql/ ์— ํ˜ธ์ŠคํŠธ๋ช…-bin.000001, ํ˜ธ์ŠคํŠธ๋ช…-bin.000002 ํ˜•ํƒœ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

 

์ด๋•Œ, log-bin ์„ค์ •์„ ๋ณ€๊ฒฝํ•˜๋ฉด Binary log ํŒŒ์ผ์˜ ๊ฒฝ๋กœ์™€ ํŒŒ์ผ๋ช…์˜ ์ ‘๋‘์–ด๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ„์—์„  log-bin=mysql์ด๋ผ ์„ค์ •ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— mysql-bin.000001, mysql-bin.000002 ์ด๋ฆ„์œผ๋กœ๋กœ Binary log ํŒŒ์ผ์ด ์ƒ์„ฑ๋œ๋‹ค.

 

server-id

์„ค์ •์—์„œ ์„œ๋ฒ„๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ ๊ณ ์œ  ID๊ฐ’์ด๋‹ค. master, slave ๊ฐ๊ฐ ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

 

 

๋„์ปค๋ฅผ ์žฌ์‹œ์ž‘ํ•˜์—ฌ ์„ค์ • ๋ณ€๊ฒฝ ์ ์šฉ ํ›„ ๋„์ปค ๋‚ด๋ถ€์— ๋‹ค์‹œ ์ ‘์†ํ•˜์—ฌ ์„ค์ •์ด ์ œ๋Œ€๋กœ ์ ์šฉ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ

$ docker restart mysql-master

$ docker exec -it mysql-master /bin/bash
$ mysql -u root -p 
mysql> SHOW MASTER STATUS\G

 

ํ˜„์žฌ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋กœ๊ทธ ํŒŒ์ผ๋ช…์ด๊ณ , Position์€ ํ˜„์žฌ ๋กœ๊ทธ์˜ ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

 

 

 

 

 

master DB์— ๊ณ„์ • ์ƒ์„ฑ

master DB์—์„œ ์‚ฌ์šฉํ•  ๊ณ„์ •์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด ๊ณ„์ •์ด slave DB์—์„œ ๋ณต์ œํ•  ์˜ˆ์ •์ด๋‹ค. dgjinsu ๋ผ๋Š” ๊ณ„์ •์„ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๊ณ , ๋ชจ๋“  ip์— ๋Œ€ํ•ด์„œ ๊ถŒํ•œ์„ ์—ด์–ด์ค€๋‹ค.

 

$ CREATE USER 'dgjinsu'@'%' IDENTIFIED BY '1234';

//sha256_password
$ ALTER USER 'dgjinsu'@'%' IDENTIFIED WITH mysql_native_password BY '1234';

$ GRANT REPLICATION SLAVE ON *.* TO 'dgjinsu'@'%';

$ FLUSH PRIVILEGES;

 

MySQL 5.8๋ถ€ํ„ฐ๋Š” Password Auth๋ฐฉ์‹์ด caching_sha2_password ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์œ„์™€ ๊ฐ™์ด ์œ ์ €๋ฅผ ์ƒ์„ฑํ•  ๋•Œ IDENTIFIED WITH mysql_native_password BY ๋กœ ์ƒ์„ฑํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์•„๋ž˜์˜ ์—๋Ÿฌ๋ฅผ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋‹ค.

error connecting to master 'replication
user@mysql-primary:3306' - retry-time: 60 retries: 1 message: Authentication plugin 'caching
sha2_password' reported error: Authentication requires secure connection.

 

 

์ „๋ถ€ ์ž…๋ ฅํ–ˆ๋‹ค๋ฉด ๋ฐฉ๊ธˆ ์ƒ์„ฑ๋œ ๊ณ„์ •์ด ๋ณด์ผ ๊ฒƒ์ด๋‹ค.

$ SELECT User, Host FROM mysql.user;

 

 

database, table์„ ๋งŒ๋“ค๊ณ  ์•„๋ฌด ๋ฐ์ดํ„ฐ๋‚˜ ์‚ฝ์ž…ํ•ด์ค€๋‹ค. 

 

 

master ์ปจํ…Œ์ด๋„ˆ๋กœ ๋Œ์•„์™€์„œ, dump๋ฅผ ํ•ด์ค€๋‹ค.

์ƒ์„ฑํ•œ dump.sql ํŒŒ์ผ์„ ๋กœ์ปฌ ํ™˜๊ฒฝ์œผ๋กœ ๊ฐ€์ ธ์™€์ค€๋‹ค. 

$ mysqldump -u root -p bookclub > dump.sql // ์ปจํ…Œ์ด๋„ˆ์—์„œ ์‹คํ–‰

$ docker cp mysql-master:dump.sql . // ๋กœ์ปฌ์—์„œ ์‹คํ–‰

 

 

5.2 slave DB ์ƒ์„ฑ

slave DB๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ์ปจํ…Œ์ด๋„ˆ mysql-slave ์ƒ์„ฑ

docker run -p 3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=1234 --link mysql-master -d docker.io/mysql

 

slave ์ปจํ…Œ์ด๋„ˆ๋„ my.cnf ํŒŒ์ผ์„ ํŽธ์ง‘ํ•ด์ฃผ์ž

์œ„์—์„œ ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ vi ์„ค์น˜ํ•ด์ค€ ํ›„ ์•„๋ž˜์™€ ๊ฐ™์ด id๋ฅผ ์„ค์ •ํ•ด์ฃผ์ž.

[mysqld]
server-id=2

 

์„ค์ •ํ–ˆ๋‹ค๋ฉด ์ ์šฉ์„ ์œ„ํ•ด docker ์ปจํ…Œ์ด๋„ˆ๋ฅผ restart

 

 

๋กœ์ปฌ ํ™˜๊ฒฝ์— ์˜ฎ๊ฒจ๋’€๋˜ dump ํŒŒ์ผ์„ slave ์ปจํ…Œ์ด๋„ˆ๋กœ ๋ณต์‚ฌํ•˜๊ณ , dump ํŒŒ์ผ์„ ์ ์šฉํ•ด์ค€๋‹ค.

$ docker cp dump.sql mysql-slave:.
$ docker exec -it mysql-slave /bin/bash

$ mysql -u root -p
mysql> CREATE DATABASE test;

mysql> exit

$ mysql -u root -p test < dump.sql

 

 

5.3 slave๋ฅผ master์™€ ์—ฐ๊ฒฐ

master mysql์— ์ ‘์†ํ•ด SHOW MASTER STATUS\G ๋ฅผ ์ด์šฉํ•ด Position์„ ํ™•์ธํ•ด์ค€๋‹ค. 

ํ˜น์€ SHOW BINARY LOG STATUS ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ™•์ธ

์ฒ˜์Œ ํ™•์ธํ–ˆ์„ ๋•Œ ๋ณด๋‹ค ์ฆ๊ฐ€ํ•œ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

mysql-slave ์ปจํ…Œ์ด๋„ˆ๋กœ ๋Œ์•„์™€ mysql-master๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  slave๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค.

mysql> CHANGE MASTER TO MASTER_HOST='mysql-master', MASTER_USER='dgjinsu', MASTER_PASSWORD='1234', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=1890;
Query OK, 0 rows affected, 8 warnings (0.04 sec)

mysql> START SLAVE;
Query OK, 0 rows affected, 1 warning (0.02 sec)

 

MASTER_HOST : master ์„œ๋ฒ„์˜ ํ˜ธ์ŠคํŠธ๋ช…

MASTER_USER : master ์„œ๋ฒ„์˜ mysql์—์„œ REPLICATION SLAVE ๊ถŒํ•œ์„ ๊ฐ€์ง„ User ๊ณ„์ •์˜ ์ด๋ฆ„

MASTER_PASSWORD : master ์„œ๋ฒ„์˜ mysql์—์„œ REPLICATION SLAVE ๊ถŒํ•œ์„ ๊ฐ€์ง„ User ๊ณ„์ •์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ MASTER_LOG_FILE : master ์„œ๋ฒ„์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋กœ๊ทธ ํŒŒ์ผ๋ช…

MASTER_LOG_POS : master ์„œ๋ฒ„์˜ ํ˜„์žฌ ๋กœ๊ทธ์˜ ์œ„์น˜

 

 

 

slave์—์„œ ์—ฐ๊ฒฐ์ •๋ณด๋ฅผ ์กฐํšŒํ•ด ๋ณด๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด mysql-master์™€ ์—ฐ๊ฒฐ๋œ ์ •๋ณด๊ฐ€ ๋‚˜์˜จ๋‹ค.

์œ„์—์„œ ์–˜๊ธฐํ–ˆ๋˜ ๋‘ ๊ฐ€์ง€ ์Šค๋ ˆ๋“œ์ธ Slave_IO ์™€ Slave_SQL ์ด ์ ์ƒ์ ์œผ๋กœ Running ๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

mysql> SHOW SLAVE STATUS\G

 

 

์ด์ œ Master ์ปจํ…Œ์ด๋„ˆ๋กœ ๋“ค์–ด๊ฐ€ ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•˜๋ฉด slave์—์„œ๋„ ์ž˜ ๋œจ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

 

 

6. SpringBoot์—์„œ DataSource ๋ถ„๊ธฐ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„๋ฅผ Source - Replica ๋กœ ์ด์ค‘ํ™” ํ•˜์˜€์œผ๋ฏ€๋กœ, ์Šคํ”„๋ง๋ถ€ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” DataSource๋„ Master-Slave ์— ๋งž๊ฒŒ 2๊ฐœ๋ฅผ ์จ์•ผํ•œ๋‹ค. readOnly = true ํŠธ๋žœ์žญ์…˜์€ Slave DataSource๋ฅผ, readOnly = false ์ธ ํŠธ๋žœ์žญ์…˜์€ Master DataSource๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ถ„๊ธฐํ•ด์•ผํ•œ๋‹ค.

 

application.yml

spring:
  datasource:
    master:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: [url]
      username: [username]
      password: [password]
    slave:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: [url]
      username: [username]
      password: [password]

 

 

DataBaseConfig.class

@Configuration
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) // ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ์ž๋™ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์„ฑ์„ ๋น„ํ™œ์„ฑํ™”
@EnableTransactionManagement // ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋ฅผ ํ™œ์„ฑํ™”
@EnableJpaRepositories(basePackages = {"test"}) // JPA ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๊ณ , ํŒจํ‚ค์ง€ ์Šค์บ” ๊ฒฝ๋กœ๋ฅผ ์ง€์ •
public class DataBaseConfig {

    // ๋งˆ์Šคํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค์ •์„ ์œ„ํ•œ ๋นˆ	
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    // ์Šฌ๋ ˆ์ด๋ธŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค์ •์„ ์œ„ํ•œ ๋นˆ
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    // ๋ผ์šฐํŒ…
    @Bean
    public DataSource routingDataSource(@Qualifier("masterDataSource") DataSource master,
                                        @Qualifier("slaveDataSource") DataSource slave) {
        ReplicationRoutingDataSource routingDataSource = new ReplicationRoutingDataSource();

        HashMap<Object, Object> sources = new HashMap<>();
        sources.put(DATASOURCE_KEY_MASTER, master);
        sources.put(DATASOURCE_KEY_SLAVE, slave);

        routingDataSource.setTargetDataSources(sources);
        routingDataSource.setDefaultTargetDataSource(master);

        return routingDataSource;
    }
    // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜๋Š” ๊ธฐ๋ณธ์ ์ธ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์„ค์ •
    @Primary
    @Bean
    public DataSource dataSource(@Qualifier("routingDataSource") DataSource routingDataSource) {
        return new LazyConnectionDataSourceProxy(routingDataSource);
    }
}

 

 

 

ReplicationRoutingDataSource.class

Spring Boot์—์„œ MySQL Replica๋ฅผ ์ด์šฉํ•ด ํŠธ๋žœ์žญ์…˜์—์„œ ์ฝ๊ธฐ ์ „์šฉ์€ slave DB์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , 

์“ฐ๊ธฐ๋Š” master DB์—์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์„ค์ •ํ•ด ๋ณด์ž. 

 

์ด๋ฅผ ์œ„ํ•ด์„œ master, slave DB ์ค‘ ์–ด๋Š DB๋ฅผ ์„ ํƒํ•˜๋Š”์ง€ ์„ค์ •ํ•˜๋Š” AbstractRoutingDataSource์™€ ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜์— slave DB ๊ฐ€ ์ปค๋„ฅ์…˜ ๋˜๋„๋ก ํ•˜๋Š”  LazyConnectionDataSourceProxy์„ ์‚ฌ์šฉํ•œ๋‹ค.

 

 

 

 AbstractRoutingDataSource๋Š” spring-jdbc ๋ชจ๋“ˆ์— ํฌํ•จ๋˜์–ด ์žˆ๋Š” ํด๋ž˜์Šค๋กœ, ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ์†Œ์Šค๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ํŠน์ • ์ƒํ™ฉ์— ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ถ”์ƒํ™”ํ•œ ํด๋ž˜์Šค์ด๋‹ค. 

 

determineCurrentLookupKey() ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜์—ฌ, ์ฝ๊ธฐ ์ „์šฉ์ผ ๊ฒฝ์šฐ slave๋ฅผ, ์•„๋‹Œ ๊ฒฝ์šฐ master๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ด์คฌ๋‹ค.

 

@Slf4j
public class ReplicationRoutingDataSource extends AbstractRoutingDataSource {
    public static final String DATASOURCE_KEY_MASTER = "master";
    public static final String DATASOURCE_KEY_SLAVE = "slave";

    @Override
    protected Object determineCurrentLookupKey() {
    	// ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜์ด ์ฝ๊ธฐ ์ „์šฉ์ธ์ง€ ํ™•์ธ
        boolean isReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
        String dataSourceKey = (isReadOnly) ? DATASOURCE_KEY_SLAVE : DATASOURCE_KEY_MASTER;
        log.info("Selected DataSource: {}", dataSourceKey);
        return dataSourceKey;
    }
}

 

 

 

์ด๋ ‡๊ฒŒ ํŠธ๋žœ์žญ์…˜์— ๋”ฐ๋ผ ๊ฐ์ž ๋‹ค๋ฅธ DB๊ฐ€ ์„ ํƒ๋˜๋Š”๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.