仙kisenon

브랜치

Kisenon의 카피온라이트 Postgres 브랜치 — LSN에서 포크, 수명 주기, 그리고 캐스케이드.

브랜치는 프로젝트 스토리지 내 로그 시퀀스 번호(LSN)를 가리키는 포인터입니다. 하나를 생성하는 것은 O(1) 행 삽입이며 데이터를 복사하지 않습니다. 브랜치는 쓰기를 진행함에 따라 분기하며, 델타만 저장됩니다.

모델

모든 프로젝트는 생성 시점부터 main 브랜치를 가집니다. main(또는 기존의 어떤 브랜치)에서 새 브랜치를 포크할 수 있습니다:

  • HEAD에서 — 새 브랜치는 부모의 현재 LSN에서 시작합니다.
  • 특정 LSN에서 — 새 브랜치는 부모의 WAL 보존 창 내 과거 LSN에서 시작합니다. 이것이 "시간 여행" 사례입니다: WAL이 여전히 보존되어 있는 한 과거의 한 지점에서 브랜치를 분기할 수 있습니다.

브랜치의 읽기는 브랜치가 분기할 때까지 부모의 페이지로 떨어집니다. 쓰기는 델타만 기록합니다. 그 결과:

  • 작은 브랜치 열 개가 있는 100 GB 프로젝트는 총 ~100 GB로 청구됩니다.
  • 브랜치를 생성하는 것은 1초 미만입니다.
  • 브랜치는 일회용입니다. 파괴적인 마이그레이션을 실행하고 브랜치를 버리면 부모는 손대지 않은 채 남습니다.

명명

브랜치 이름은 사용자에게 보이는 레이블이며, 부모 프로젝트로 범위가 지정됩니다. 제약 조건은 프로젝트 이름과 일치합니다:

  • 1–63자.
  • ^[a-zA-Z][a-zA-Z0-9_-]*$.
  • 프로젝트 내에서 고유.

내부 브랜치 id(9b1e4d7a-2c3f-4a85-b6d0-1e2f3a4b5c6d 같은 UUID)가 안정적인 참조입니다. API에 대해 스크립팅할 때는 이름이 아니라 id를 사용하세요. 이름은 변경될 수 있습니다.

상태 머신

브랜치는 다음을 거쳐 전이합니다:

creating → ready → deleting → deleted
  • creating — 컨트롤 플레인이 브랜치를 스토리지 계층에 등록하는 중입니다. 일반적으로 1초 미만이며, 스토리지가 부하를 받으면 더 길어집니다.
  • ready — 브랜치를 엔드포인트에 연결하고 쓰기를 받을 수 있습니다.
  • deleting — 캐스케이드 진행 중: 이 브랜치의 모든 엔드포인트가 중지되고 제거되는 중입니다.
  • deleted — 종료 상태. 행은 감사를 위해 짧은 기간 동안 보존된 다음 가비지 컬렉션됩니다.

CLI는 모든 브랜치의 현재 상태를 보여줍니다:

keon branches list --project <project-id>

생성

keon branches create --project <project-id> --name my-feature --parent main

과거 LSN에서 브랜치를 만들려면 --parent-lsn <lsn>을 전달하세요:

keon branches create \
  --project <project-id> \
  --name pre-migration \
  --parent main \
  --parent-lsn 0/1A2B3C4D

LSN은 프로젝트의 WAL 보존 창 내에 있어야 합니다. 그 너머로 컴팩션되었다면 브랜치 생성이 실패합니다.

삭제

--cascade를 주면 브랜치 삭제가 연결된 모든 엔드포인트를 제거합니다. 주지 않으면 엔드포인트가 있는 동안 삭제가 거부됩니다.

  1. 브랜치의 모든 엔드포인트가 중지되고 제거됩니다.
  2. 브랜치 자체가 철거됩니다.
  3. 스토리지는 pageserver 컴팩션에 의해 비동기적으로 회수됩니다.
keon branches delete <branch-id> --cascade

프로젝트의 main 브랜치는 단독으로 삭제할 수 없습니다 — API가 409 cannot_delete_main_branch를 반환합니다. 대신 프로젝트를 삭제하세요.

자식 브랜치가 남아 있는 브랜치는 409 has_child_branches로 거부됩니다 — 먼저 자식을 삭제하세요. 재부모화는 일어나지 않습니다. 스냅샷이 있는 브랜치는 409 branch_has_snapshots로 거부됩니다. 먼저 스냅샷을 삭제하세요.

재설정 및 복원

콘솔의 브랜치 상세 페이지에서 ⋯ 동작 메뉴는 루트가 아닌 모든 브랜치에 대해 두 가지 재포크 작업을 노출합니다:

  • 부모로 재설정 — 브랜치를 부모의 현재 HEAD에서 재포크합니다. 원래 포크 이후 브랜치에서 이루어진 모든 쓰기가 폐기됩니다. 브랜치의 엔드포인트는 교체 중 잠시 일시 중지됩니다.
  • 특정 시점으로 복원 — 선택한 LSN 또는 UTC 타임스탬프(RFC 3339)에서 브랜치를 재포크합니다. 그 시점 이후의 쓰기는 폐기됩니다.

둘 다 비동기적으로 실행됩니다: 콘솔이 요청을 발행하고, 재포크가 완료되면 브랜치가 ready로 돌아갑니다. 루트(main) 브랜치는 재설정할 수 없습니다 — 재설정할 부모가 없습니다.

스냅샷

스냅샷은 특정 시점의 LSN을 고정하여 WAL 보존 한계를 넘어서도 복원 가능하게 유지합니다. 스냅샷이 없으면 복원 대상은 그 WAL이 여전히 보존되어 있는 동안에만 도달할 수 있지만, 스냅샷은 그 지점을 무기한 주소 지정 가능하게 유지합니다.

브랜치 상세 페이지의 스냅샷 탭은 브랜치의 스냅샷을 나열하고 새로 하나를 캡처할 수 있게 합니다. 각 행은 다음을 제공합니다:

  • 복원 — 스냅샷의 고정된 LSN에서 브랜치를 재포크합니다.
  • 삭제 — 스냅샷을 드롭합니다(기저 LSN은 더 이상 고정되지 않으며 컴팩션에 의해 회수될 수 있습니다).

관련 문서

  • 프로젝트 — 브랜치를 소유하는 것.
  • 엔드포인트 — 클라이언트 트래픽을 받기 위해 브랜치에 연결되는 것.
  • 개념 — 브랜치를 무료로 만드는 스토리지 / 컴퓨트 분리.
브랜치 · Kisenon