Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DB replication 적용 #636

Merged
merged 2 commits into from
Nov 17, 2023
Merged

DB replication 적용 #636

merged 2 commits into from
Nov 17, 2023

Conversation

cookienc
Copy link
Member

@cookienc cookienc commented Oct 10, 2023

관련이슈

참고사항

  •  DB 백업 및 복제

아래 명령어로 dump.sql를 만들어서 복제를 해줬습니다. 이 파일을 scp 를 이용해 replica ec2로 보냈습니다.


mysqldump -u root -p -v --databases <DATABASE_NAME> \
--quick --single-transaction --routines --set-gtid-purged=ON \
--triggers --extended-insert --source-data=2 > dump.sql
  •  DB source, replica 설정
    /etc/my.cnf 파일에 아래처럼 각각 설정해주었습니다.
    복제 방식은 바이너리 기반과 GTID 기반이 있는데, GTID기반으로 사용했습니다.

[이유] 1. 바이너리 기반은 복제가 중간에 중지가 되면 복구하기가 어렵다 - 바이너리로그는 `이름 + 저장 위치`로 구별되므로 복제가 중단되면 어디부터 시작되는지 모른다고 합니다. 2. 설정방법이 차이가 별로 없다.
# Replication - Source
server-id=1
log-bin=binlog
gtid-mode=ON
enforce-gtid-consistency=ON

# Replication - Replica
server-id=2
log-bin=binlog 
gtid-mode=ON # GTID 모드
enforce-gtid-consistency=ON # GTID 모드
relay_log=mysql-relay-bin
relay_log_purge=ON # rela_log 자동 삭제
read_only # 읽기 전용 DB로 사용
super_read_only # Replica에서 root도 dml이나 ddl을 실행할 수 없음
log_replica_updates=ON # 복제된 내용을 자신의 바이너리 로그에 저장(추후에 승급되면 사용 가능)
  •  스프링 요청에서 DataSource 분리
    [참고사항]
@Profile("deploy")
@Configuration
public class DataSourceConfig {

// …
    @Bean
    @Primary
    public DataSource dataSource(@Qualifier(ROUTING_NAME) final DataSource replicationRoutingDataSource) {
        return new LazyConnectionDataSourceProxy(replicationRoutingDataSource);
    }
}

원래 Transaction이 시작되면 connection이 시작되는데 lazyConnectionDataSourceProxy를 사용해서 sql을 실행하기 직전까지 connection을 가져오는것을 미룹니다(readonly 설정이 설정된 뒤에 가져오기 위해서인 듯)
public class RoutingDataSource extends AbstractRoutingDataSource {

    public static RoutingDataSource createDefaultSetting(final Map<Object, Object> dataSources) {
        final RoutingDataSource routingDataSource = new RoutingDataSource();
        routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));
        routingDataSource.setTargetDataSources(dataSources);
        return routingDataSource;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        final boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();

        if (readOnly) {
            return DataSourceType.REPLICA;
        }

        return DataSourceType.SOURCE;
    }
}

AbstractRoutingDataSource를 상속받아서 determineCurrentLookupKey를 override해줬는데 여기서 transaction이 readonly인지 boolean으로 반환해서 datasource를 replica나 source로 보내줍니다.

참고 : 후디, 허브, 공식문서

ps 블로그에 더 이쁘게 해서 올릴게요

@cookienc cookienc added ✨ feat 기능 개발하고 오겠습니다. 💙 BE 백엔드 작업입니다. labels Oct 10, 2023
@cookienc cookienc self-assigned this Oct 10, 2023

import java.util.Map;

public class RoutingDataSource extends AbstractRoutingDataSource {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뜯어보셨군요 jdbc

shb03323
shb03323 previously approved these changes Oct 10, 2023
Copy link
Collaborator

@shb03323 shb03323 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다.

싱크 문제는 다음에 이야기해용

@cookienc cookienc merged commit 3f9b9a5 into woowacourse-teams:dev/BE Nov 17, 2023
1 check passed
@cookienc cookienc deleted the feat/627 branch November 17, 2023 05:47
@cookienc cookienc restored the feat/627 branch November 17, 2023 07:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💙 BE 백엔드 작업입니다. ✨ feat 기능 개발하고 오겠습니다.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants