- OpenAI의
Habitat은 40개 지리적 리전에서 10억 명 이상의 사용자에게 500페타바이트 이상의 데이터를 제공하며, Azure Cosmos DB 기반 스토리지를 안정성, 읽기 성능, 운영 효율 순으로 개선해 옴
- 컨테이너를 워크로드별로 분리하자 장애 범위는 줄었지만 제품팀의 용량 계획 부담이 커졌으며,
부하 격리 기능을 개선해 공유 멀티 테넌트 컨테이너를 기본으로 사용하는 방식으로 돌아옴
- 대형 계정의 리전 장애 조치와 복귀 과정에서 심각한 장애를 겪은 뒤, Azure와
프로덕션 규모 테스트 및 전 계층 공동 모니터링을 수행하는 공동 관리 체계를 구축함
- 데이터 배치와 선택적 복제,
CDC 기반 통합 캐시, Rust 재작성 등을 결합해 전 세계 읽기 지연 시간의 p50을 약 120ms에서 약 10ms로 줄임
- 다음 10억 명의 사용자를 지원하기 위해
엑사바이트 규모 맞춤형 스토리지를 개발 중이며, 최대 QPS를 낮추는 대신 분리형 스토리지와 물리적 복제로 플래시 용량을 줄이는 절충을 택함
Habitat의 규모와 확장 우선순위
Habitat은 OpenAI 제품에 빠르고 안정적인 데이터 접근을 제공하는 온라인 스토리지 플랫폼으로, 40개 지리적 리전에 걸쳐 10억 명 이상의 사용자에게 밀리초 단위로 응답해야 함
-
단순한 클라이언트 라이브러리와 데이터베이스에서
500페타바이트 이상을 제공하는 전 세계 분산 스토리지 플랫폼으로 발전함
-
1부는 Python 클라이언트가 서비스로 발전한 과정과 Python 서비스 확장 기법을 다룸
-
2부에서는 Azure 팀과 협력한
Azure Cosmos DB 확장, 공동 관리 컨테이너를 활용한 멀티 테넌시, 전 세계 읽기 성능 개선을 다룸
-
확장 우선순위는
안정성 → 성능 → 효율성이며, 핵심 제품 트래픽을 안정적으로 처리한 뒤 전 세계 지연 시간과 대규모 운영을 개선함
멀티 테넌시의 절충과 Cosmos DB의 구조
싱글 테넌시는 장애 영향 범위와 담당 영역을 명확히 나누고 워크로드를 격리하기 쉽지만, 팀과 제품이 늘면 운영 비용과 과잉 프로비저닝이 커짐
- 각 제품팀이 자체 시스템과 용량 계획을 책임져야 함
멀티 테넌시는 전문성을 갖춘 중앙 데이터베이스팀이 리소스를 관리할 수 있지만, 한 테넌트가 다른 테넌트의 리소스를 잠식하는 노이지 네이버 문제가 있음
- Habitat은
공유 컨테이너 → 전용 컨테이너 → 공유 컨테이너 기본 사용의 순서로 전환함
- 멀티 테넌시 구현은 아직 초기 단계이며, 가능한 한 Cosmos DB 기본 기능을 활용해 자체 구현에 대한 투자를 미룸
Azure Cosmos DB 계정은 컨테이너 집합과 복제 정책을 정의하며, 각 컨테이너에는 초당 요청 단위인 RU/s로 처리량을 프로비저닝함
- 데이터는 논리 파티션 키로 샤딩되며, 논리 키별 저장량과 처리량 한도가 명시돼 있음
- 여러 논리 파티션 키가 더 적은 수의
물리 파티션에 배치됨
- 저장량이 임계값을 넘거나 프로비저닝된 처리량을 유지하는 데 필요하면 물리 파티션이 분할됨
1단계: 기본 기능만으로는 부족했던 부하 격리
- 초기에는 계정마다
기본 컨테이너 하나를 사용하고 클라이언트 부하를 제한 없이 받아들였으며, 논리 파티션 키당 10K RU/s 한도에 백프레셔를 맡김
- 클라이언트가
논리 파티션 키를 직접 선택하면서 서로 다른 제품의 user_id
, workspace_id
가 충돌함
-
서로 다른 사용 사례가 같은 키의 한도를 공유해 사용자별 전체 처리량이 제한됨
-
이전 Postgres 환경에서도 요청이 집중되는 조직이나 핫 키가 데이터베이스 전체를 마비시키는 문제가 있었음
-
당시에는 핫 키 캐싱과 캐시 미스 처리용
리스 메커니즘으로 기반 데이터베이스에 부하가 몰리는 것을 막음
-
실제 처리량 제한은
물리 파티션 단위로 적용되므로, 같은 물리 파티션에 속한 논리 키들이 한도를 공유함
-
논리 키 하나가 명시된 10,000 RU/s를 독립적으로 사용할 수 있는 구조가 아님
-
소수 사용자를 위한 제품 기능의 워크로드가 핵심 로그인과 가입 흐름을 방해하기도 함
-
컨테이너 처리량은 물리 파티션에 대체로 균등하게 배분되므로,
저장량 증가에 따른 분할이 파티션별 처리 용량을 낮춤
-
총처리량을 그대로 둔 채 파티션 수만 늘어나면 각 파티션의 처리량 몫이 줄어듦
-
블롭처럼 저장량이 큰 워크로드에서는 요청률이 일정해도 데이터 증가만으로 처리 용량이 부족해질 수 있음
2단계: 전용 컨테이너가 줄인 장애와 늘린 운영 부담
컨테이너 분리는 독립적인 물리 파티션을 확보해 파티션 키 충돌과 노이지 네이버의 영향을 같은 컨테이너 내부로 제한함
-
다만 컨테이너마다 별도 용량 계획이 필요하므로, 처음에는 강한 격리가 필요한 중요한 신규 사용 사례에 적용함
-
물리 파티션 수에 맞춰 총처리량을 조정하는
스크립트를 함께 사용해 처리 용량이 낮은 파티션 문제를 관리함
-
기존 핵심 사용 사례는 데이터를 마이그레이션하지 않는 한
공유 기본 컨테이너에 남아 있었음
-
기본 컨테이너의 부하와 프로덕션 장애가 늘자, 신규 서비스와 대규모 제품 기능마다 전용 컨테이너를 프로비저닝함
-
사이트 전체 장애를 많이 피하고 영향을 개별 기능이나 서비스의 성능 저하로 제한할 수 있었음
-
전용 컨테이너에서는
출시 시 급격한 부하 증가를 개별 팀이 대비해야 했음
-
공유 컨테이너에서는 신규 사용 사례가 0에서 100만 QPS로 늘어도 전체 부하 변화가 작을 수 있지만, 전용 컨테이너에서는 내부 테스트 기준의 1,000배에 이를 수 있음
-
사전 확장을 잊은 제품팀 때문에 출시 당일 장애 대응 중 급하게 컨테이너를 확장하는 일이 발생함
-
워크로드를 모아 전체 증가세를 완만하게 만드는
멀티 테넌시의 이점을 잃으면서, 용량 계획에 깊은 제품 지식이 필요해짐
-
증가 추세에 따라 처리량을 늘리는 기본 스크립트만으로 급격한 변화를 정확히 예측하기 어려웠음
-
사실상 모든 제품팀의 참여가 필요했고, 팀별 프로비저닝 관리 수준의 편차 때문에 조직 확장에 한계가 생김
3단계: 격리를 유지하며 공유 컨테이너로 복귀
-
중앙에서 용량을 계획하지 않는 구조의 한계를 해결하기 위해 Azure와 함께
공유 테넌시 설계를 개선함
핫 키 스로틀링은 요청이 가장 많이 몰리는 키부터 제한해, 하나의 키가 물리 파티션의 가용 처리량을 모두 소모하는 일을 막음
서비스 품질(QoS) 은 대량 삽입과 데이터 추출 같은 오프라인 요청에 낮은 우선순위를 부여함
-
낮은 우선순위 요청을 먼저 스로틀링해 최종 사용자의 대화형 요청을 보호함
-
기존
서버리스 모드는 처리 용량이 낮은 파티션 문제를 해결했지만, 저장량만으로 확장하고 물리 파티션당 5K RU/s로 제한돼 RU 사용량이 많은 워크로드에는 부족했음
-
Azure Cosmos DB 팀이 OpenAI용으로 개선한 모드에서는 물리 파티션당 최대
10K RU/s까지 확장할 수 있음
-
저장량뿐 아니라 RU 사용량에 따른 분할도 지원해 컨테이너를 수동으로 모니터링하고 확장할 필요를 없앰
-
이 변경으로
공유 컨테이너를 기본으로 사용하면서 워크로드 격리를 유지하고 제품팀의 사전 및 지속적인 용량 계획 부담을 크게 줄임
-
이후 수개월 동안 제품 개발 속도가 빨라졌는데도 프로비저닝이나 노이지 네이버 관련 장애가 발생하지 않음
관리형 서비스에서 공동 관리 서비스로
- OpenAI 규모에서는
관리형 서비스를 사용하는 것만으로 운영을 맡길 수 없었으며, 테스트와 대시보드 공유, 직접 소통, 장애에 대한 공동 책임이 필요해짐
- 가장 큰 Cosmos DB 계정은 수십 페타바이트를 저장하고
2,000만 QPS 이상을 처리함
- OpenAI가 아는 범위에서는 이 규모로 Cosmos DB를 구축한 기업은 OpenAI뿐임
2024년 말 리전 정전으로 대형 계정을 보조 리전으로 전환하는 데 몇 시간이 걸린다는 사실을 확인함
-
OpenAI와 Azure 모두 해당 규모의 장애 조치를 미리 테스트하지 못했음
-
약 한 달 뒤 원래 리전으로 복귀할 때도 연결이 한꺼번에 몰려 게이트웨이가 과부하에 빠짐
-
게이트웨이 모드 클라이언트가 일부 물리 파티션만 복귀한 상태에서도 모두 즉시 원래 리전으로 연결하고 요청을 보내는 동작이 원인이었음
-
양사는 각 장애의 근본 원인을 수정하는 데 그치지 않고
설계부터 운영까지 공동 작업하는 체계로 전환함
-
서비스 계층부터 물리 스토리지까지 공동 모니터링하고, 프로덕션과 같은 규모의 비프로덕션 계정에서 변경을 테스트함
-
SDK 공동 테스트와 개선, 계정 규모 산정 및 확장 모범 사례 수립을 수행함
-
Teams 직접 소통과 지원 단계를 거치지 않는 상대 팀 긴급 호출 수단을 마련함
-
지난 1년간
제어 영역과 게이트웨이 확장성을 공동 개선함
-
메타데이터 파티션 보호를 위한 게이트웨이 부하 보호와 메타데이터 캐싱을 추가함
-
연결 풀링과 재사용으로 Python
habitat-service
프로세스군의 부하를 줄임
-
가능한 워크로드를 같은 위치에 배치하고, 서로 다른 VPC로 핵심 워크로드와 오프라인 워크로드를 격리함
-
조직 경계를 넘는
공동 엔지니어링이 지난 1년간 Cosmos DB 안정성을 유지하는 데 핵심적인 역할을 함
전 세계 읽기 성능: 데이터 배치와 선택적 복제
-
2025년 시스템이 안정화된 뒤에는
리전 간 지연 시간이 사용자와 제품팀의 다음 제약이 됨
-
컴퓨팅과 스토리지 용량이 서로 다른 리전에 있어 원격 요청이 불가피했음
-
제품팀은 클라이언트 캐싱, 요청 일괄 처리, 읽기와 쓰기 최소화, 핵심 처리 경로 밖으로 작업 이동 등을 활용함
-
이런 설계는 데이터베이스 문제에 대한 내성을 높였지만 제품을 복잡하게 만들고 개선 주기를 늦춤
-
2026년에는 Habitat 요청의
90% 이상을 차지하는 읽기를 다층적으로 최적화함
사용자 가까이에 데이터를 저장하면 지연 시간을 줄일 수 있지만 물리적 클라우드 용량의 제약을 받음
-
데이터 레지던시 요구를 충족하기 위해 여러 Azure 리전에 계정을 운영하지만, 그 밖의 사용자에게는 가까운 데이터 배치를 널리 적용하지 못함
-
많은 리전이 배정된 사용자 트래픽에 필요한 대규모 스토리지를 수용하지 못함
-
데이터센터 용량, 전력, 냉각이 제한되면 같은 위치의 스토리지와 서비스 제공용 컴퓨팅 중 어디에 용량을 배분할지 선택해야 함
작고 지연 시간에 민감한 데이터 세트만 광범위하게 복제함
- 모든 요청에 필요한 인증 메타데이터 등은 다수의 보조 리전을 둬 컴퓨팅과 Habitat 사이의 왕복 시간을 줄임
- 일부 계정은 트래픽을 처리하는 40개 Azure 리전 전체에, 다른 계정은 대륙별 최소 한 리전에 복제함
- 복제 토폴로지가 다른 계정 사이에서 데이터를 옮기기 위해 클라이언트가 의식할 필요 없는
데이터 이동 및 라우팅 계층을 계획보다 일찍 구축함
- 복제도 용량 제약이 있어 엄선한 소수의 데이터 세트에만 적용함
CDC 기반 캐싱과 Rust로 줄인 지연 시간
- Habitat은 설정, 상태, 속성 등 비교적 작은 작업 데이터 집합에 읽기가 집중돼
분산 캐싱에 적합함
- 사용자 요청을 처리하는 인프라 가까이에 Valkey 서버를 배치하고, 최근 접근한 객체와 에지의 복사본을 저장하는 룩어사이드 캐시를 통합함
- 멀티 리전에서는 캐싱으로 리전 간 지연 시간을 숨길 수 있음
TTL만으로는 캐시 적중률과 데이터 최신성을 동시에 확보하기 어려움
-
짧은 TTL은 오래된 데이터를 줄이지만 재조회가 늘어 캐싱 효과가 떨어짐
-
긴 TTL은 적중률을 높이지만 오래된 데이터를 더 오래 제공해 사용자 경험과 제품 동작의 예측 가능성을 해침
-
애플리케이션 쓰기 시
명시적 캐시 무효화를 수행해도 부분 장애와 예외 상황을 정확히 처리하기 어려움
-
멀티 리전에서는 네트워크 안정성이 낮고 캐시와 스토리지 복제 사이의 경합도 발생함
-
TTL을 병행하면 오래된 데이터가 남는 최대 시간을 제한할 수 있지만 근본적인 절충은 남음
-
Meta의
TAO 같은 시스템을 참고해 Cosmos DB 변경 피드의 변경 데이터 캡처(CDC) 로 수초 내에 전 세계 캐시 무효화를 전파함
-
로컬 서비스가 변경 피드를 소비해 갱신된 원본의 캐시를 무효화함
-
다음 읽기에서 캐시 미스가 발생하면 최신 데이터로 다시 채워, 높은 적중률과 낮은 데이터 노후화를 함께 추구함
-
서비스 코드를 Python에서
Rust로 재작성해 프록시 오버헤드와 지연 시간을 줄임
-
여러 개선을 합쳐 전 세계 읽기 지연 시간의
p50이 약 120ms에서 약 10ms로 12배 개선됨
-
느린 요청은 여전히 캐시 미스 후 먼 리전의 기반 스토리지에 접근해야 함
-
추가 용량과 스토리지 효율을 확보하면서 처음부터 사용 위치 가까이에 데이터를 배치하는 문제에 대응할 계획임
수백만 건의 변경을 전달하는 CDC 플랫폼
CDC는 수천 개 컨테이너와 수백만 개 파티션에서 초당 수백만 건의 변경을 캡처해 100개 이상의 Kafka 토픽으로 전달함
-
캐시 외에도 최종적 일관성을 갖는 보조 인덱스, 데이터 이동 파이프라인, 오프라인 분석, 실시간 제품 기능을 구동함
-
제품 개발자가 계정과 컨테이너 위치, 리전별 감시 서비스, 워커와 Kafka 및 소비자의 규모를 직접 관리하지 않도록
콜백 등록 인터페이스로 복잡성을 추상화하는 것이 목표임
-
클라이언트가 행 변경 시 호출할 함수를 등록하면 내부 연결과 확장은 플랫폼이 처리함
내부 제어 영역은 필요한 컨테이너의 캡처 여부를 지속 확인하고, 읽을 Cosmos 리전을 선택하며, 여러 리전의 수천 개 워커에 작업을 배분함
-
복제본 리전과 낮은 우선순위의 피드 읽기를 활용해 지연 시간에 민감한 트래픽을 보호함
-
워커 충돌, 컨테이너 문제, 리스 저장소 오류, 잘못된 구성, 대상 시스템 장애에 대응하도록
장애 격리와 복구를 강화함
-
워커 수명 주기와 리스 처리를 견고하게 만들고 스트림별 장애를 격리함
-
구성 변경과 배포에 안전장치를 두고, 영구적인 전달 실패가 후속 처리를 막지 않도록 데드 레터 큐를 사용함
-
리전 장애 시 리더를 다른 Cosmos 리전으로 전환함
-
Azure CDC SDK를 수정해 체크포인트를 메모리에 모은 뒤 주기적으로 플러시하도록 효율을 높임
다음 10억 명을 위한 스토리지
-
소규모 팀은
좁은 스토리지 API, 지속적인 Python 서비스 확장, 가장 시급한 엔지니어링 과제 우선 처리로 빠른 성장을 지원함
-
인프라의 세부 사항을 추상화해 제품 개발 속도를 높이는 것이 Habitat과 CDC 플랫폼의 공통 가치임
-
더 큰 규모의 데이터 복제를 위해 용량이 큰 Habitat 데이터 유형에 최적화한
엑사바이트 규모 맞춤형 온라인 스토리지를 자체 개발 중임
Rockset의 RocksDB Cloud 코어와 Raft 기반 복제를 결합함
-
Azure Cosmos DB와 동일한 문서 모델을 구현함
-
최대 QPS를 낮추는 대신 분리형 스토리지와 물리적 복제로 필요한 플래시 용량을 줄임
댓글과 토론