SQLite 복제 도구 선택: Litestream·rqlite·cr-sqlite는 언제 쓸까?

SQLite 복제본을 하나 더 띄워 뒀는데, 서버가 멈추자 주문 저장도 같이 멈췄다. 복구용 복제와 쓰기를 이어 가는 복제 중 우리 서비스에는 어느 쪽이 필요할까?

SQLite 복제 도구 선택: Litestream·rqlite·cr-sqlite는 언제 쓸까?
세 줄 요약
  • 서버를 잃은 뒤 복구할 자료가 필요하다면 Litestream의 비동기 복제와 최근 쓰기 유실 가능성을 살펴야 한다.
  • rqlite는 연결된 투표 노드 과반수가 있어야 쓰기를 계속하며, 조회의 최신성도 읽기 모드에 따라 달라진다.
  • cr-sqlite는 기기의 독립 변경을 병합하는 방식으로, 오프라인 편집과 동기화를 겨냥한다.

제품 이름보다 장애가 났을 때의 요구가 먼저다

rqlite 개발자 Philip O'Toole은 10월 23일 공개한 회고에서 2014년부터 이어진 분산 SQLite의 흐름을 돌아봤다. 그의 핵심 설명은 하나의 기술이 다른 기술을 모두 대체했다는 이야기가 아니다. 합의, 변경 스트리밍, 독립 수정의 병합은 서로 다른 질문에 답하는 설계라는 것이다.

먼저 답할 질문대표 접근핵심 조건
서버를 잃은 뒤 DB를 복원할 수 있나?Litestream의 비동기 복제복제 지연·복원 절차
일부 노드가 멈춰도 쓰기를 이어 갈 수 있나?rqlite의 Raft 합의서로 통신하는 투표 노드 과반수
각 기기가 오프라인에서 바꾼 내용을 합칠 수 있나?cr-sqlite의 변경 병합변경 내역 교환과 병합 규칙

Litestream은 복구할 자료를 계속 밖으로 보낸다

Litestream은 별도 프로세스가 SQLite의 WAL 변경을 비동기로 복제한다. 장애 뒤에는 저장된 스냅샷과 후속 변경을 담은 LTX 파일로 데이터베이스를 복원한다. 서버를 잃어도 돌아갈 자료를 확보하는 방식이다.

비동기라는 조건은 중요하다. 운영 문서는 원격으로 복제되기 전 서버에 치명적인 장애가 나면 최근 쓰기를 잃을 수 있다고 설명한다. 기본 S3 복제 간격은 1초로 안내하지만, 이를 어떤 장애에서도 손실이 최대 1초라는 보장으로 읽으면 안 된다.

최신 문서에는 VFS를 이용한 읽기 복제 기능도 있다. 따라서 Litestream을 단순히 “조회는 못 하는 백업”으로 정의할 수는 없다. 다만 원격에서 읽을 수 있다는 기능과 쓰기마다 여러 노드의 합의를 받는 동작은 별개다.

rqlite는 쓰기 전에 연결된 과반수가 필요하다

rqlite 클러스터 안내에 따르면 투표 노드 3개 구성은 2개, 5개 구성은 3개가 살아 있고 서로 통신해야 한다. 투표하지 않는 읽기 복제본은 이 수에 포함되지 않는다. 노드를 추가했다고 모든 장애 조합에서 쓰기를 계속할 수 있는 것은 아니다.

rqlite FAQ는 어느 노드에 요청을 보내든 실제 변경은 리더를 거친다고 설명한다. 리더가 아닌 노드는 쓰기 요청을 전달한다. 각 노드가 따로 쓰고 나중에 내용을 맞추는 방식이 아니다.

기존 SQLite 파일을 직접 수정하던 앱에 그대로 끼우는 교체품도 아니다. 쓰기는 HTTP API를 통해야 한다. 분산의 주된 목적은 장애 대응이며, 쓰기 처리량을 노드 수에 맞춰 늘리는 구조가 아니다.

복제된 데이터라고 모든 조회가 같은 보장을 받지는 않는다

rqlite의 읽기 일관성은 요청 모드에 따라 달라진다. 기본 Weak는 리더가 로컬 상태를 확인해 읽으며, 리더가 바뀌는 짧은 구간에는 오래된 결과를 줄 수 있다.

Linearizable은 과반수 응답과 필요한 변경 적용을 확인하는 더 강한 읽기 보장이다. 반면 None은 클러스터 연결 확인 없이 로컬 데이터를 읽으므로 오래된 결과를 허용한다. 읽기 속도와 최신성 요구를 함께 정해야 하는 이유다.

오프라인 편집은 또 다른 설계가 필요하다

cr-sqlite는 여러 기기의 독립 변경을 합치기 위해 SQLite에 CRDT 기반 복제 기능을 더한다. 프로젝트가 제시하는 용도에는 기기 간 동기화, 실시간 협업과 오프라인 편집이 있다.

변경 내역을 조회하고 반영하는 crsql_changes와 그 내용을 다른 기기로 보내는 네트워크 코드는 구별된다. 확장을 로드하는 것만으로 모든 기기의 전송 경로까지 자동으로 마련되는 것은 아니다.

자주 묻는 질문

rqlite에 노드를 늘리면 쓰기도 그만큼 빨라지는가?

모든 쓰기는 리더를 거친다. 노드 추가를 통한 쓰기 수평 확장이 목적은 아니다.

기본 읽기 모드면 항상 최신 결과를 받는가?

기본 Weak에는 리더 교체 시 오래된 결과를 받을 수 있는 구간이 있다. 필요한 보장에 맞춰 읽기 모드를 선택해야 한다.

복구까지 기다릴 수 있는지, 최근 쓰기를 잃어도 되는지, 연결이 끊긴 기기에서도 수정해야 하는지를 먼저 정해야 한다. 그 답이 같은 SQLite 위에서 서로 다른 복제 방식을 고르는 기준이다.