TL;DR
- Asana는 고객 데이터를 페타바이트 규모로 저장하고 100개가 넘는 MySQL 인스턴스에 고객 ID 기준으로 샤딩하며, 캐싱과 운영 제어를 통해 데이터베이스 확장성을 관리함.
- EAV(엔터티-속성-값) 모델과 물리적 인덱스 테이블의 비정규화로 LunaDb의 캐시 무효화를 지원하지만, 단일 객체 쓰기가 여러 인덱스에 전파될 수 있음.
- Asana는 LunaDb, LunaServer Redis, 트랜잭션 제한, 비동기 작업 역압력, 연결 풀링을 활용하고, 대부분의 데이터베이스에서 복제본 운영을 피함.
- 급격한 부하, 운영 중 데이터베이스 엔진 업그레이드, 특정 대형 고객의 핫스폿 샤드가 주요 부담이며, 지역 내 샤드 이동은 드물지만 고객을 지역 간에 옮기는 데 샤드 이동 시스템을 활용함.
- AI 에이전트가 읽기·쓰기 처리량과 저장량을 늘리고 인프라 비용 예측을 어렵게 하면서, 성능·비용·운영 단순성 사이의 균형이 확장 우선순위로 부상함.
Asana 데이터 모델
- Asana는 고객 데이터를 EAV 모델로 저장함. 예를 들어
Task객체의name: str및is_completed: bool필드는 속성값 단위로 표현됨. - LunaDb가 무효화할 캐시 데이터를 판별하기 쉽도록 데이터를 물리적 인덱스 테이블에 비정규화함.
- 이 구조에서는 단일 객체 값에 대한 쓰기가 여러 물리적 인덱스로 전파될 수 있음. 객체 캐싱과 쿼리 캐싱에 미치는 영향은 이 글의 범위 밖임.
MySQL 인스턴스 간 고객 데이터 분산
- 고객 데이터는 100개가 훨씬 넘는 물리적 MySQL 인스턴스에 분산되며, 고객 ID를 파티션 키로 사용함.
- 한 고객의 데이터는 단일 MySQL 인스턴스에 저장됨. 다만 도메인 샤딩 모델에 맞지 않는 일부 메타데이터는 예외임.
- 각 데이터베이스는 여러 고객이 함께 사용하는 멀티테넌트 구조임. 고객마다 데이터베이스를 하나씩 두는 방식은 Asana 규모에 적합하지 않음.
- Asana가 샤딩을 이전한 시점의 자세한 내용은 당시의 블로그 글에서 다룸.
- 도메인 모델에 깔끔하게 들어맞지 않는 데이터도 있음. 예를 들어 Asana 계정은
foo.com과bar.com에 동시에 연결될 수 있음. - 이러한 교차 도메인 데이터는 소수의 전용 데이터베이스에 저장함.
- 여러 곳에서 공유되는 데이터베이스에 대한 시스템의 의존도를 낮추기 위해 가능한 곳에서 데이터를 비정규화함.
- Asana는 여러 데이터 지역과 FedRAMP 파티션을 지원하며, 지역 전반에 동일한 샤딩 전략을 적용함.
대규모 데이터베이스 계층 운영 방식
- 캐싱에 크게 의존함. 분산 캐시인 LunaDb와 LunaServer Redis를 사용해 데이터베이스 계층의 복잡성을 줄이고, 대형 인스턴스 및 MySQL 트랜잭션 엔진의 확장 한계에 맞춘 운영의 필요성을 낮춤.
- 표현력과 단순한 쿼리 성능을 맞바꿈.
Task의 필드가 한곳에 모여 있지 않는 등, 단일 행 조회로 처리할 수 있었을 단순한 읽기 작업도 여러 테이블에서 데이터를 모아야 할 수 있음. 이는 그래프 쿼리 언어에서 더 풍부한 표현력을 얻기 위한 선택임. - 장기 트랜잭션 종료 기능으로 문제가 있는 쿼리를 제어함. 장기 트랜잭션 종료는 OLTP 데이터베이스 운영의 일반적인 관행임.
- Asana의 그래프 쿼리는 실행 시간이 길어질 수 있으며, 데이터베이스는 추가 객체 사본과 연결 오버헤드를 추적해야 함. 대기 중인 트랜잭션이 쌓이면 데이터베이스 성능이 빠르게 저하될 수 있음.
- Asana의 ORM은 사용자가 트랜잭션을 직접 열 수 있도록 함. 애플리케이션 로직이 트랜잭션을 정리하지 않으면 데이터베이스 오버헤드가 발생할 수 있음.
- 비동기 작업에 역압력을 적용함. 변동성이 큰 읽기·쓰기 부하의 가장 큰 원인은 비동기 작업임. Infrastructure Resource Management가 이러한 작업의 리소스 사용량을 추적하고 작업을 제한해 데이터베이스와 다른 인프라 리소스의 건전성을 유지함.
- 대부분의 경우 데이터베이스 복제본을 사용하지 않음. 최종 일관성 모델을 사용하는 LunaDb와 안전하게 상호작용하는 읽기·쓰기 트랜잭션에서 복제본을 활용하는 방식은 복잡함.
- 복제본을 온라인으로 유지하는 데는 기본적인 운영 및 비용 오버헤드도 따름. LunaDb의 성능을 고려하면 확장 관점에서 복제 계층이 대체로 필요하지 않다고 판단해, 추가 복잡성과 유지 비용을 피함.
- 다만 고객 규모가 매우 큰 특정 데이터베이스에서는 읽기 복제본을 운영함.
- 연결 풀링으로 연결을 재사용함. Asana는 데이터베이스마다 장기 연결과 단기 연결을 함께 사용함. 교차 도메인 데이터베이스에서는 생성 후 종료되는 단기 연결이 훨씬 많음.
RDS Proxy를 연결 풀로 사용해 빈번하게 생성·종료되는 연결 수를 줄였으며, 그 결과 데이터베이스 안정성이 향상되고 CPU 사용량이 크게 감소함.- 지역 내 샤드 이동은 드물게 수행함. 최신 데이터베이스는 실제 확장 한계에 도달하기 전까지 수직 확장이 가능한 범위가 큼. 샤드 이동 시스템은 미국에서 유럽으로 이동하는 경우처럼 Asana의 멀티리전 상품 간 고객 이동에도 사용함.
아키텍처에 부담을 주는 지점
- 급격한 부하: 캐시되지 않은 읽기 트래픽 급증, 예약된 비동기 작업, 예상하지 못한 쿼리 패턴이 데이터베이스를 일시적으로 압도할 수 있음. 역압력 메커니즘과 회로 차단기가 대부분의 부하를 흡수하며, 이를 계속 조정함.
- 운영 부담: LunaDb가 물리적 바이너리 로그(binlog) 파일과 오프셋에 강하게 연결돼 있어, 다운타임을 최소화하는 데이터베이스 엔진 업그레이드에 현재 많은 시간이 소요됨.
- 핫스폿 샤드: 일부 대형 엔터프라이즈 고객은 부하를 불균등하게 분산시킴. 이례적으로 큰 고객 샤드는 기존 확장 가정을 깨는 방식으로 트래픽 패턴을 바꿀 수 있어, 개별 사례에 맞춰 처리하는 경우가 많음.
AI 작업이 바꾸는 확장 우선순위
- AI 에이전트는 상시 작동하므로 읽기·쓰기 처리량을 늘리고, 호스팅에 드는 한계 비용을 통해 저장량도 증가시킴.
- 과거에는 컴퓨팅, 메모리, 저장장치 비용이 시간이 지나며 낮아진다고 가정할 수 있었지만, 이제는 그렇지 않은 것으로 보임. 이에 따라 새 기능의 비용과 해당 인프라의 호스팅 비용 간 균형이 주요 고려 사항임.
- 이러한 과제에는 단순한 해답이 없으며, 복잡한 엔지니어링 절충이 필요함.
- 팀은 개발 초기에 쿼리 성능 문제를 찾아내는 ‘시프트 레프트(shift left)’ 방식, 제품 기능 수준의 관측 가능성과 비용 귀속 개선, 데이터베이스 엔진 변경 작업의 수작업 부담 감소도 검토함.
- AI 시대에 맞춰 Asana 인프라를 확장하는 동안 성능, 비용, 운영 단순성의 균형을 갖춘 복원력 있는 시스템을 구축하고, 새로운 요구를 예측하며 도구를 지속적으로 개선하는 데 초점을 둠.
각주
- ¹ 도메인 샤딩 모델에 깔끔하게 들어맞지 않는 일부 메타데이터는 예외임.
- ² 고객 규모가 매우 큰 특정 데이터베이스에서는 읽기 복제본을 운영함.
팀 정보
- Spencer Yu는 모든 Asana 사용자 데이터의 기반 클라우드 저장 계층을 구축하고 관리하는 Core Storage Infrastructure 팀의 기술 리드임.
- 이 작업은 팀과 이전 팀 구성원이 함께 수행했으며, 참여자에는 Walter Li, Cynthia Gao, Debbie Pao, Claire Chen, David Hecker, Gaurav Ranade, Shreyas Patil, Shoaib Akbar, Ed Korthof, Rohan Batra, Sanchit Sinha, Mary Mathews, Bryant Lin, Jana Bantupalli 등이 포함됨.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요