Amazon Aurora 글로벌 데이터베이스와 쓰기 전달
사이트 구성 간 Amazon Aurora의 글로벌 데이터베이스를 활용하여 4개 리전 사이에 데이터베이스 복제 구성을 하면서, 유용하게 사용했던 "글로벌 데이터베이스 쓰기 전달" 기능에 대해 간략하게 소개해 드리고자합니다.
1. Amazon Aurora 글로벌 데이터베이스
오로라 글로벌 데이터베이스를 여러 리전에 걸쳐 복제하는 기술로 바이너리 로그를 기반으로 복제를 수행하는 교차 리전 복제와 달리 글로벌 데이터베이스는 오로라 클러스터 스토리지 볼륨을 이용합니다. 스토리지 계층에서 복제가 이뤄지기 때문에 데이터베이스 엔진 계층에서 수행되는 교차 리전 복제보다 복제에 소요되는 지연시간이 짧으며, 데이터베이스는 오로지 쿼리에 대한 처리 전용으로 사용됩니다.(복제를 위해 사용하는 리소스가 없기 때문에 쿼리 처리에 더 뛰어남)
https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html
2. 글로벌 데이터베이스 쓰기 전달
쓰기 DB와 읽기 DB가 별도로 구성되어 있는 경우 별도 쿼리 라우팅을 지원하는 DB 프록시를 사용하지 않는 이상 어플리케이션에서는 쓰기 엔드포인트와 읽기 엔드포인트를 별도로 두어 쿼리에 따라 엔드포인트를 달리 구성해야합니다. 하지만 오로라 글로벌 데이터베이스는 "쓰기 전달" 기능을 지원하여 보조 리전 클러스터에서 "쓰기 전달" 기능 활성화 시 읽기 엔드포인트에서 쓰기 엔드포인트로 자동으로 쿼리를 포워딩할 수 있습니다.
하지만 쓰기 전달 기능으로는 DML(데이터 조작어, SELECT/INSERT/DELETE/UPDATE)만 포워딩이 가능하며, 제약 사항이 있기 때문에 상세 내용은 아래 공식 문서를 참고 부탁드립니다.
3. 오로라 글로벌 데이터베이스 생성 및 쓰기 전달 구성
1) 오로라 클러스터 생성
먼저 쓰기 엔드포인트로 사용할 주 리전에서 오로라 클러스터를 생성합니다. 현재 테스트 환경의 주 리전은 버지니아 북부입니다. 클러스터 생성 시 "글로벌 데이터베이스 기능을 지원하는 버전 표시" 옵션을 통해 글로벌 데이터베이스를 지원하는 버전으로 생성합니다. 글로벌 데이터베이스의 경우 db.t3 타입의 인스턴스 클래스를 지원하지 않습니다. db.r4 혹은 db.r5 클래스로 인스턴스 클래스를 설정합니다.
2) 보조 리전 추가
주 리전에 쓰기 엔드포인트 생성이 완료되었다면 작업 버튼을 눌러 "리전 추가"를 클릭합니다.
테스트 환경에서는 글로벌 데이터베이스의 이름을 "premisan-test-global"로 설정하고 보조 리전은 서울 리전으로 선택했습니다. 글로벌 데이터베이스의 인스턴스 클래스 제약 사항은 보조 리전에도 그대로 적용됩니다.
네트워크 설정은 적절하게 선택해줍니다.
쓰기 전달 기능을 활성화하기 전과 비교해보기 위해 먼저 쓰기 전달 기능은 활성화하지 않겠습니다. 만약 바로 쓰기 전달 기능을 사용하시고자 한다면 이 부분에서 "읽기 복제본 쓰기 전달 활성화"를 체크해줍니다.
테스트 환경에서는 보조 리전의 클러스터 이름을 "premisan-test-seoul"로, 인스턴스 이름을 "premisan-test-seoul-instance-1"로 설정하였습니다.
클러스터 스토리지 볼륨을 이용하여 보조 리전의 클러스터가 생성되어 사용 가능 상태로 표시됩니다.
3) 쓰기 전달 기능 비활성화 시 쿼리 및 속도 테스트
현재 쓰기 전달 기능을 사용하지 않은 상태의 엔드포인트 정보로 접속하여 쿼리에 어느정도 지연이 발생하는지 확인해보겠습니다. 접속 테스트에 사용할 MySQL 클라이언트는 서울 리전에 있습니다.
쓰기 엔드포인트(버지니아 북부) - premisan-test-us.cluster-caima9b9eivi.us-east-1.rds.amazonaws.com
읽기 엔드포인트(서울) - premisan-test-seoul.cluster-ro-cvkaud92ikgf.ap-northeast-2.rds.amazonaws.com
서울 리전의 인스턴스에서 버지니아 북부의 쓰기 엔드포인트로 쿼리 수행 시 평균적으로 0.19~0.24초가 소요되었습니다.(테이블 레코드 수 100개 기준)
서울 리전의 인스턴스에서 서울 리전의 읽기 엔드포인트로 쿼리 수행 시 0.00~0.01초가 소요되었습니다.(테이블 레코드 수 100개 기준)
읽기 엔드포인트에서 INSERT 쿼리 수행 시 아래와 같이 read-only 에러가 발생합니다.
4) 쓰기 전달 활성화
이제 쓰기 전달 기능을 활성화해보겠습니다. 서울 리전의 보조(읽기) 클러스터를 선택한 뒤, 수정 버튼을 눌러 수정 페이지로 이동합니다. 수정 가능한 옵션 중 "읽기 복제본 쓰기 전달" 옵션을 체크한 뒤, 수정을 완료합니다. (수정되는 동안 서비스 중단은 발생하지 않았습니다.)
5) 쓰기 전달 테스트
글로벌 데이터베이스 쓰기 전달 기능 활성화 시 보조 클러스터에서 읽기 일관성 정도 제어를 위해 aurora_replica_read_consistency 파라미터를 반드시 설정해야합니다. 해당 파라미터는 세션 수준 파라미터로 접속한 세션마다 설정해줘야합니다. 기본 값은 NULL이기 때문에 쓰기 전달 옵션을 활성화해도 해당 파라미터를 지정하지 않으면 계속 read-only 에러가 발생합니다. aurora_replica_read_consistency 파라미터의 종류는 eventual, session, global 총 세가지로 간략한 의미는 아래와 같습니다.
쓰기 전달의 격리 및 일관성 관련 가이드
https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/aurora-global-database-write-forwarding.html#aurora-global-database-write-forwarding-isolation
# 인서트의 결과 반영을 대기하지 않고 셀렉트 실행(대기 시간이 발생하지 않으나, 셀렉트의 결과가 최신 데이터가 아닐 수 있음)
set aurora_replica_read_consistency = 'eventual';
# 인서트의 결과를 세션 데이터에 의해 반영해서 셀렉트 실행(세션에 의한 데이터 일치, 대기 시간 발생하지 않음)
set aurora_replica_read_consistency = 'session';
# 인서트의 결과를 모두 전파할때까지 대기 후 셀렉트 실행(대기 시간 발생하나 정확한 데이터)
set aurora_replica_read_consistency = 'global';**
아래 내용을 보조 리전의 읽기 클러스터에서 수행합니다.
# 파라미터 확인
show variables like '%aurora_replica_read_consistency%';
# aurora_replica_read_consistency 파라미터의 값을 eventual 로 설정
set aurora_replica_read_consistency = 'eventual';
INSERT 쿼리 테스트
다시 SELECT 시 아래와 같이 정상적으로 101번째 레코드가 인서트된 것을 확인할 수 있습니다.
여러번 인서트하여 테스트 시 평균적으로 0.20
0.21 초 정도가 소요됩니다.(레코드 1개 인서트 시) 주의할 점은 aurora_replica_read_consistency 파라미터의 값이 eventual 이나 session 일 경우에는 읽기 지연이 전혀 없으며, 쓰기 지연만 0,20초 내외 발생하지만, aurora_replica_read_consistency 파라미터의 값을 global 로 설정하는 경우 읽기 쿼리에서 0.7
2.0초 사이의 지연이 발생합니다.
이런 현상은 aurora_replica_read_consistency 값을 global 로 설정하는 경우 SELECT 쿼리 수행 시 주 리전 및 모든 보조 리전의 값을 최신으로 받아온 뒤 수행하기 때문에 발생하는 지연으로, 정확도는 높으나, 지연시간이 크게 발생하는 것을 확인할 수 있습니다. 때문에 쿼리할 데이터의 정확도가 중요한지 여부에 따라 파라미터의 값을 조정하여 최단 지연시간을 확보하는 것이 좋겠습니다. 또한 위에 쓰기 전달 기능 관련 제약 사항에서 말씀드린 것과 같이 DDL(데이터 정의어, CREATE/ALTER/DROP)은 전달이 불가능합니다.
4. 결론
Amazon Aurora 글로벌 데이터베이스를 사용 시 클러스터 스토리지 볼륨 복제를 통해 복제로 인한 오버헤드 없이 다른 리전에 보조(읽기) 클러스터를 생성 가능하고, 쓰기 전달 옵션 활성화 시 어플리케이션에서는 보조 리전의 읽기 엔드포인트만으로 읽기/쓰기 쿼리 모두 가능합니다. 때문에 글로벌 데이터베이스 쓰기 전달 기능 사용 시 아래와 같은 장점을 기대할 수 있습니다.
1) 어플리케이션에서는 보조 리전의 읽기 엔드포인만 커넥션에 사용하기 때문에 소스 구성 및 관리에 용이하다.
2) 어플리케이션(서울) 상에서 주 리전(버지니아 북부)의 DB로 읽기 쿼리를 수행하는 것에 비해 보조 리전(서울)의 DB로 읽기 쿼리를 수행하는 것이 지연시간이 짧다.(네트워크 지연 시간 때문에 당연한 결과)
3) 쓰기 전달을 사용하여 읽기 엔드포인트에 쓰기 쿼리 시 발생하는 지연시간은 쓰기 엔드포인트에 직접 쿼리하는 것과 지연시간에서 별반 차이가 없다.
결론적으로 속도상의 큰 이점은 없이 비슷하나, 어플리케이션 상에서 하나의 DB 엔드포인트를 가질 수 있다는 것이 쓰기 전달 기능의 핵심인 것으로 보입니다.