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

[1단계 - DB 복제와 캐시] 프린(남기범) 미션 제출합니다. #65

Open
wants to merge 19 commits into
base: given53
Choose a base branch
from

Conversation

GIVEN53
Copy link
Member

@GIVEN53 GIVEN53 commented Oct 18, 2024

안녕하세요 알파카 🦙🦙 이렇게 리뷰로 만나뵙게 되어 영광이네요 ㅎㅎ
잘부탁드립니다

복제 지연 처리 방법

전제

  • WAS 이중화
  • replica 2대 이상
  • 쿠폰 생성 후 바로 조회하는 시나리오
    • 관리자가 쿠폰 등록에 성공했을 때 쿠폰 조회 페이지로 바로 redirect 되는 경우
    • 다른 관리자가 쿠폰 조회

1. semi-sync (반동기 복제)

MySQL 복제 방식의 기본값은 async(비동기)입니다. 그래서 replica에 정상적으로 복제되었는지 확인하지 않고 source의 트랜잭션 종료 및 결과를 반환합니다.
semi-sync 중 after sync(5.7.2 버전부터 도입 및 semi-sync 방식의 기본값) 방식을 사용하면 여러 replica 중 하나의 서버relay log에 기록이 완료되었다는 ACK를 회신한 후에 source의 트랜잭션 종료 및 결과를 반환합니다.
semi-sync를 사용하려면 옵션 활성화 외에도 추가 플러그인을 설치해야 합니다

고려 사항

  1. semi-sync의 흐름은 아래와 같아요
    image
    replication SQL applier thread가 relay log를 스토리지 엔진에 쓸 때 오래 걸린다면 replica로 요청했을 때 해당 데이터가 존재하지 않을 수 있습니다

  2. replica가 여러개일 경우
    image
    하나의 replica가 ACK를 보내면 source의 트랜잭션이 종료됩니다. 이 때 아직 반영이 완료되지 않은 replica로 읽기 요청하면 복제 지연이 발생할 수 있습니다 rpl_semi_sync_source_wait_for_replica_count 파라미터로 source가 받아야 할 ACK 개수를 설정할 수 있지만 성능은 그만큼 떨어집니다.

  3. source는 replica의 ACK를 받기위해 timeout(기본값 10초)만큼 기다리고, 이 시간을 초과하면 async로 동작합니다. ACK 응답은 TCP/IP로 통신하기 때문에 네트워크 레이턴시도 고려해야 합니다 결국 timeout이 발생해서 async로 동작한다면 복제 지연이라는 근본적인 문제를 해결할 수 없고, 복제 지연을 해결하기 위한 적절한 timeout값을 설정하는데도 어려움이 있습니다

결론적으로 semi-sync방식은 데이터 무손실, 정합성을 위한 옵션이고 복제 지연을 처리하기 위한 방법은 아니라고 생각했습니다

AWS RDS는 어떤 배포 옵션을 사용했느냐에 따라 동기 방식이 달라지더라구요
다중 AZ 클러스터semi-sync방식을 사용합니다 고가용성, fail over에 초점을 두고 있어서 데이터 정합성을 위해 이 방식을 사용하는 것이 아닐까하는 생각이 들었어요
단순히 읽기 전용 복제본만 생성할 경우 async방식을 사용합니다 읽기 성능 향상, 트래픽 분산 목적이고 fail over는 수동으로 해주어야 해요 자동 fail over를 위해 active-standby를 추가 구성할 경우 standby로 복제는 sync로 처리됩니다(standby는 fail over용이기 때문에 읽기 트래픽을 처리할 수 없음)

2. 생성 후 일정 시간 지연

쿠폰 생성 후 조회는 관리자만 수행하기 때문에 복제가 완료될 때까지 쿠폰 생성에 대한 응답을 지연합니다
상황에 따라 복제 지연이 얼마나 되는지 예측할 수 없고, 아무리 관리자여도 무한정 대기할 수 없기 때문에 제외했습니다

3. 캐시

[ 로컬 캐시 ]
image
WAS는 이중화되어 있기 때문에 로컬 캐시로는 복제 지연을 해결할 수 없습니다

[ 리모트 캐시 ]
image
Redis와 같은 캐시 서버를 외부에 두는 방법입니다 쓰기 시에는 write through, 읽기 시에는 Look Aside 전략을 사용합니다.

고려 사항

  1. redis가 다운되면 복제 지연이 발생할 수 있습니다.
  2. 쓰기를 수행하는 WAS에서 db나 redis에 쓰기 작업 중 에러가 발생하면 데이터 정합성 문제를 해결해야 합니다.
  3. 모든 데이터를 메모리에 저장할 수 없기 때문에 TTL을 설정해야 합니다. 하지만 semi-sync의 timeout과 같이 적절한 TTL을 계산하기 어렵습니다 (TTL을 1분으로 설정하고 cache miss가 발생했는데, 복제가 2분 걸린다면?)

캐시를 사용하는 것은 Disk I/O를 줄이고 메모리에서 훨씬 빠르게 데이터를 가져오기 위함인데, 복제 지연을 해결하기 위한 대안과는 조금 거리가 멀다고 느껴졌어요

4. Multi Threaded Replication

image

MySQL 5.6 버전부터 병렬 복제가 추가되었습니다 replica_parallel_workers(워커 스레드 수)는 8.0.27 버전부터 4개가 기본값입니다 (Dockerfile에 명시된 MySQL 버전은 8.0.34)

replica_parallel_type(벙렬 실행 타입)

  • DATABASE 기반(5.6 버전부터 도입): 서로 다른 데이터베이스에 수행된 트랜잭션만 병렬 복제
  • LOGICAL_CLOCK 기반(5.7버전부터 도입, 8.0.27 버전부터 기본값): 데이터베이스에 종속되지 않고 바이너리 로그에 쓰는 타임스탬프를 기준으로 병렬 복제

binlog_transaction_dependency_tracking(LOGICAL_CLOCK 방식)

  • COMMIT_ORDER
  • WRITESET
  • WRITESET_SESSION

바이너리 그룹 커밋 등 내용이 어려워서 키워드만 학습하고 넘어갔습니다

reference: https://dev.mysql.com/blog-archive/improving-the-parallel-applier-with-writeset-based-dependency-tracking/

5. replica DB에 데이터가 없으면 source DB 조회 (선택)

image

관리자만 쿠폰을 생성하고, 쿠폰 생성이 자주 발생하지 않기 때문에 source DB의 부하가 적을 것이라고 생각합니다
I/O가 총 2번 발생하고 DB 커넥션을 2개 점유하는 것때문에 사용자에게 영향을 미친다면 관리자의 쿠폰 조회는 source DB만 사용하도록 변경해볼 것 같아요

@GIVEN53 GIVEN53 self-assigned this Oct 18, 2024
@slimsha2dy slimsha2dy self-requested a review October 20, 2024 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant