캐시 아키텍처
Note
이 페이지는 Tuist 캐시 서비스 아키텍처의 기술적 개요를 제공합니다. 주로 서비스의 내부 동작을 이해해야 하는 셀프 호스팅 사용자와 기여자를 대상으로 합니다. 캐시를 사용하기만 하는 일반 사용자는 이 내용을 읽을 필요가 없습니다.
Tuist 캐시 서비스는 빌드 아티팩트를 위한 콘텐츠 주소 지정 스토리지(CAS)와 캐시 메타데이터를 위한 키-값 저장소를 제공하는 독립형 서비스입니다.
개요#
이 서비스는 로컬 SQLite 메타데이터와 함께 2계층 스토리지 아키텍처를 사용합니다:
- 로컬 디스크: 저지연 캐시 히트를 위한 기본 스토리지
- S3: 아티팩트를 영구적으로 저장하고 제거 후 복구를 가능하게 하는 내구성 있는 스토리지
- SQLite: 아티팩트 접근 추적, 고아 파일 정리, 백그라운드 작업 및 키-값 캐시 데이터를 위한 로컬 메타데이터
flowchart LR
CLI[Tuist CLI] --> NGINX[Nginx]
NGINX --> APP[Cache service]
NGINX -->|X-Accel-Redirect| DISK[(Local Disk)]
APP --> S3[(S3)]
APP -->|auth| SERVER[Tuist Server]
컴포넌트#
Nginx#
Nginx는 진입점 역할을 하며 X-Accel-Redirect를 사용하여 효율적인 파일 전송을 처리합니다:
- 다운로드: 캐시 서비스는 인증을 검증한 후
X-Accel-Redirect헤더를 반환합니다. Nginx는 디스크에서 직접 파일을 제공하거나 S3에서 프록시합니다. - 업로드: Nginx는 요청을 캐시 서비스로 프록시하며, 캐시 서비스는 데이터를 디스크로 스트리밍합니다.
콘텐츠 주소 지정 스토리지#
아티팩트는 샤딩된 디렉터리 구조로 로컬 디스크에 저장됩니다:
- 경로:
{account}/{project}/cas/{shard1}/{shard2}/{artifact_id} - 샤딩: 아티팩트 ID의 처음 네 문자가 2단계 샤드를 생성합니다(예:
ABCD1234→AB/CD/ABCD1234)
SQLite 메타데이터#
캐시 서비스는 두 개의 SQLite 데이터베이스를 사용합니다:
- 기본 메타데이터 DB:
cache_artifacts, 고아 파일 스캔 커서, Oban 작업 및 기타 서비스 메타데이터를 저장합니다. - 키-값 DB: 전용 SQLite 파일에
key_value_entries와key_value_entry_hashes를 저장합니다.
키-값 저장소는 아티팩트 메타데이터와 고아 파일 정리 상태에 영향을 주지 않고 SQLite 증분 자동 압축을 사용할 수 있도록 별도의 데이터베이스로 분리되어 있습니다.
S3 통합#
S3는 내구성 있는 스토리지를 제공합니다:
- 백그라운드 업로드: 디스크에 쓴 후 아티팩트는 매분 실행되는 백그라운드 워커를 통해 S3 업로드 대기열에 추가됩니다
- 온디맨드 하이드레이션: 로컬 아티팩트가 없을 때, 아티팩트가 로컬 디스크로의 백그라운드 다운로드 대기열에 추가되는 동안 프리사인된 S3 URL을 통해 요청이 즉시 처리됩니다
디스크 제거#
이 서비스는 여러 백그라운드 프로세스를 사용하여 디스크 공간을 관리합니다:
- CAS 디스크 제거는
cache_artifacts를 기반으로 LRU 의미 체계를 사용합니다 - 디스크 사용량이 85%를 초과하면 사용량이 70%로 떨어질 때까지 가장 오래된 아티팩트가 삭제됩니다
- 로컬에서 제거된 후에도 아티팩트는 S3에 남아 있습니다
- KV 제거는 보존 기간에 따라 오래된 키-값 항목을 제거하며, 구성된 크기 예산을 초과하여 성장할 때 전용 KV 데이터베이스를 축소할 수도 있습니다
고아 파일 정리#
이 서비스는 디스크 아티팩트를 위한 고아 파일 정리 워커도 실행합니다:
- 디스크에 존재하지만 해당
cache_artifacts행이 없는 파일을 스토리지 트리에서 스캔합니다. - 이는 파일이 디스크에 기록되었지만 SQLite 버퍼 플러시가 완료되기 전에 메타데이터 기록이 손실된 경우 발생할 수 있습니다.
- 진행 중인 업로드와의 경합을 피하기 위해 안전 윈도우보다 최신인 파일은 무시됩니다.
- 고아 파일이 삭제되고 나중에 다시 요청되면 다음 캐시 미스로 인해 다시 업로드되므로 시스템이 자체 복구됩니다.
인증#
캐시는 /api/projects 엔드포인트를 호출하고 결과를 캐싱하여(성공 시 10분, 실패 시 3초) 인증을 Tuist 서버에 위임합니다.
요청 흐름#
다운로드#
sequenceDiagram
participant CLI as Tuist CLI
participant N as Nginx
participant A as Cache service
participant D as Disk
participant S as S3
CLI->>N: GET /api/cache/cas/:id
N->>A: Proxy for auth
A-->>N: X-Accel-Redirect
alt On disk
N->>D: Serve file
else Not on disk
N->>S: Proxy from S3
end
N-->>CLI: File bytes
업로드#
sequenceDiagram
participant CLI as Tuist CLI
participant N as Nginx
participant A as Cache service
participant D as Disk
participant S as S3
CLI->>N: POST /api/cache/cas/:id
N->>A: Proxy upload
A->>D: Stream to disk
A-->>CLI: 201 Created
A->>S: Background upload
API 엔드포인트#
| 엔드포인트 | 메서드 | 설명 |
|---|---|---|
/up | GET | 상태 확인 |
/metrics | GET | Prometheus 메트릭 |
/api/cache/cas/:id | GET | CAS 아티팩트 다운로드 |
/api/cache/cas/:id | POST | CAS 아티팩트 업로드 |
/api/cache/keyvalue/:cas_id | GET | 키-값 항목 가져오기 |
/api/cache/keyvalue | PUT | 키-값 항목 저장 |
/api/cache/module/:id | HEAD | 모듈 아티팩트 존재 여부 확인 |
/api/cache/module/:id | GET | 모듈 아티팩트 다운로드 |
/api/cache/module/start | POST | 멀티파트 업로드 시작 |
/api/cache/module/part | POST | 파트 업로드 |
/api/cache/module/complete | POST | 멀티파트 업로드 완료 |