본문 바로가기
★ 프로젝트 + 트러블 슈팅 ★

AWS RDS + MySQL Replication 진행순서 및 트러블슈팅

by 리승우 2022. 12. 14.

아래와 같은 문제상황을 가정하여 생각해본 결과,

I/O부하 방지를 위한 DB이중화 (main-replication)을 도입해야겠다는 생각이 들어 이를 진행하게 되었다.

 

https://desirelsw.tistory.com/170

 

단일 서버 성능개선 트러블 슈팅

[프로젝트 현 상황] > E커머스 웹 구현중 (ex. 쿠팡, G마켓) > 특정 시간대에 특정 상품의 재고한정 특가이벤트 기능 추가예정 https://github.com/OnNaNOn/OMG GitHub - OnNaNOn/OMG Contribute to OnNaNOn/OMG development by

desirelsw.tistory.com

 

깃허브 이슈는 아래와 같다

https://github.com/OnNaNOn/OMG/issues/178

 

I/O부하 방지를 위한 DB이중화 (main-replication 도입) · Issue #178 · OnNaNOn/OMG

💡 이슈 내용 단일 DB로 운영할 시에 벌어지는 문제 (I/O부하)에 대한 해결방안이 필요하다. 🔎 문제 분석 현재 프로젝트는 일 평균 사용자가 10만명인 상태임. 이를 단일 DB로만 운영할 시에 I/O부

github.com

아래에서는, 어떻게 Main-Replication을 적용할 수 있게 되었는지와 그 해결과정을 적으려고 한다.

 

 

Main-Replication 설명

웹 계층은 로드밸런서로 인해 부하 분산을 한다면 데이터 계층은 어떻게 부하를 분산해야 하는가??
데이터 계층의 부하를 분산시키는 방법으로 주(Main)-부(Replication)관계를 설정하고 데이터 원본은 주 서버에, 사본은 부 서버에 저장하는 방식이 있다. 즉, 데이터베이스 다중화라는 기술로 해결할 수 있다.

 

쓰기 연산(write operation)은 메인에서만 지원하고,

부 데이터베이스는 주 데이터베이스로부터 그 사본을 전달받아 읽기 연산(read opertation)만을 지원한다.

 

데이터베이스를 변경하는 명령어들, 가령 insert, delete, update 등은 주 데이터베이스로만 전달되어야 한다.

대부분의 애플리케이션은 읽기 연산의 비중이 쓰기 연산보다 훨씬 높다.

따라서 통상 부 데이터베이스의 수가 주 데이터베이스의 수보다 많다.

 

데이터베이스를 다중화하면 다음과 같은 이점이 있다.

  1. 더 나은 성능: 주-부 다중화 모델에서 모든 데이터 변경 연산은 주 데이터베이스 서버로만 전달되는 반면 읽기 연산은 부 데이터베이스 서버들로 분산된다. 병렬로 처리될 수 있는 질의(query)의 수가 늘어나므로, 성능이 좋아진다.

  2. 안전성(reliability): 자연 재해 등의 이유로 데이터베이스 서버 가운데 일부가 파괴되어도 데이터가 보존될 수 있다.

  3. 가용성(availability): 데이터를 여러 지역에 복제해 둠으로써, 하나의 데이터베이스 서버에 장애가 발생하더라도 다른 서버에 있는 데이터를 가져와 계속 서비스를 할 수 있게 된다.

데이터베이스를 다중화하게 될 경우의 구성은 다음과 같다.


 

[STEP 01. AWS 설정]

01-1. Read Replica 생성

 

01-2. 읽기 전용 복제본 생성 옵션

  1. DB 인스턴스 식별자 작성
  2. 스토리지 자동 조정 활성화 OFF
  3. 퍼블릭 액세스 가능
  4. 읽기 전용 복제본 2개 생성

    ※주의사항
    복제본의 가용영역은 꼭 main RDS와 같은 가용영역으로 설정해야 한다!
    ex) 아래 이미지

 

[STEP 02. Spring 설정]

구성

  • @Transactional(readOnly = true) 인 경우는 Replication DB 접근
  • @Transactional(readOnly = false) 인 경우에는 Main DB 접근

[필자가 작성한 Spring설정 git코드]

https://github.com/iswoos/main-replication

 

GitHub - iswoos/main-replication: main-replication 적용코드

main-replication 적용코드. Contribute to iswoos/main-replication development by creating an account on GitHub.

github.com

 

 

[문제상황 해결]

1. application.yml파일 로드불가 상태

@ConfigurationProperties를 이용하여 yml의 특정 설정값들을 읽으려하였으나,

Spring Boot Configuration Annotation Processor not configured에러가 발생하였다.

그럼으로써 application.yml에 있는 slave-list값들이 연동되지 않았다는 표시가 떠서 작동이 불가하였다.

해당 이슈를 해결하고자, build.gradle의 dependencies에 하기와 같이 설정한 후 다시 build를 진행하였다.

dependencies {
...
	annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" // Use ConfigurationProperties
}

 

 

build 후에는 아래와 같이 변경되었다.

 

몇가지 확인을 해본 결과, 캐시가 쌓여서 오작동이 일어나는 경우가 있다는 글을 발견하였다. 그리하여 캐시 제거를 위해 아래와 같이 추가 처리하였다.

 

● 1.  프로그램에서 상단 메뉴바에 file를 클릭합니다. 그리고 "Invalidate Caches"를 선택합니다.

 

[참고내용]

https://earth-95.tistory.com/103

 

[Springboot, IntelliJ] Re-run Spring Boot Configuration Annotation Processor to update generated metadata

이슈 원인 @ConfigurationProperties를 사용하여 yaml의 특정 설정값들을 읽으려했고, 이때 하기와 같이 Spring Boot Configuration Annotation Processor not configured 에러가 발생했습니다. 해당 이슈를 해결하고자 buil

earth-95.tistory.com

 

 

2. p6spy로 인한 오류

해당 블로그를 참조하여, 에러를 해결하였다.

기존에 build.gradle에 있는 p6spy를 제거함으로써 문제를 해결하였다.

 

[참고내용]

https://devs0n.tistory.com/61

 

Spring Data JPA - Write, Read Only 분리 적용하기 - 2. 무력화 되는 경우

이전 포스팅을 통해 Spring Data JPA를 사용하면서 AbstractRoutingDataSource, LazyConnectionDataSourceProxy를 사용하여 Write, Read Only DB를 분리하여 사용하는 방법의 원리를 알아보았다. 그럼 이 설정을 무력화하

devs0n.tistory.com

 

3. JPA entityManager설정 오류

아래와 같이, 내가 사용할 패키지 경로를 "com.ono.omg"대신 대체하여 교체함으로써, 올바르게 JPA에서 사용할 부분을 세팅하였다.

// JPA 에서 사용할 entityManager 설정
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        EntityManagerFactoryBuilder entityManagerFactoryBuilder = createEntityManagerFactoryBuilder(jpaProperties);
        return entityManagerFactoryBuilder.dataSource(dataSource()).packages("com.ono.omg").build();
    }
    
    # 내가 사용할 패키지 경로를 "com.ono.omg" 를 대체하여 넣어주면 된다.

 

[테스트 실행결과]

  1. /test/java/aws/masterslave/service/ProductServiceSimpleTest.SLAVE_읽기()
  • Case: READ
  • Required: @Transaction(readOnly=True)
  • Result: Slave
  •   

 

  1. /test/java/aws/masterslave/service/ProductServiceTest.비관적_락()
  • Case: PessimisticLock
  • Required: STOCK = 1000, THREAD_COUNT = 900
  • Result: STOCK - THREAD_COUNT = 100

 

  1. JMeter
  • Case: time: 7sec , Request: 200


    DB분산을 처음 해봤는데, 확실히 어려운 것 같다.
    하지만 이번에도 좋은 경험이였다.

 

 

[참고링크]

https://junghwanta.tistory.com/16

 

2. Database - Replication( + AWS Read Replica)

Replication 데이터베이스의 안정성과 관련된 기능중 Replication에 대해 공부를 하였다. Replication은 여러가지 DB 서버가 있을 때, 각각의 서버가 동일한 데이터를 가지도록 하는 기술을 말한다. (사실

junghwanta.tistory.com

https://velog.io/@backtony/Spring-AWS-RDS%EB%A1%9C-MySQL-Replication-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-feat.-%EB%8B%A4%EC%A4%91-AZ

 

Spring - AWS RDS로 MySQL Replication 적용하기 (feat. 다중 AZ)

모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다.(공부한 내용을 정리하는 Github와 이 모든 내용을 담고 있는 블로그가 있습니다. )데이터베이스 이중화 방식 중 하

velog.io

https://github.com/backtony/blog-code/blob/master/mysql-master-slave/src/main/java/com/example/mysqltest/db/DbConfig.java

 

GitHub - backtony/blog-code: 개인 블로그 예제 code

개인 블로그 예제 code. Contribute to backtony/blog-code development by creating an account on GitHub.

github.com

http://kwon37xi.egloos.com/m/5364167

 

Java 에서 DataBase Replication Master/Slave (write/read) 분기 처리하기

대규모 서비스 개발시에 가장 기본적으로 하는 튜닝은 바로 데이터베이스에서 Write와 Read DB를 Replication(리플리케이션)하고 쓰기 작업은 Master(Write)로 보내고 읽기 작업은 Slave(Read)로 보내어 부하

kwon37xi.egloos.com

https://jojoldu.tistory.com/506

 

Spring Batch ItemReader에서 Reader DB 사용하기 (feat. AWS Aurora)

일반적으로 서비스가 커지게 되면 DB를 여러대로 늘리게 됩니다. 이때 가장 첫 번째로 고려하는 방법이 Replication 입니다. 즉, 1대의 마스터 DB와 여러대의 Slave DB를 두는 것이죠. 데이터의 변경은

jojoldu.tistory.com

 

댓글