-
TigerBeetle는 이중 입출금 회계 처리에 특화된 OLTP 데이터베이스로, 안전성과 빠른 처리 속도를 목표로 개발됨
-
Viewstamped Replication 합의 프로토콜과 strong serializability 기준을 지원하며, 고경합, 고처리량 작업에 최적화된 구조를 가짐
-
결함 허용 및 장애 복원력에 매우 신경 쓴 설계와 테스트 절차를 갖추고, 다양한 장애 상황에서 데이터 손실 없는 동작을 지향함
- 업그레이드, 테스트, 연산 모델, 클러스터 장애 복원력 등에서 다양한 버그와 성능 이슈가 Jepsen 테스트로 발견, 대응 가능성 개선됨
- 최신 버전에서는 Ring 기반 복제 성능, 클라이언트 오류 처리, 로깅·쿼리 정확성 등 여러 개선점과 버그 픽스가 제공됨
TigerBeetle 소개
- TigerBeetle은 이중 입출금(Double-entry bookkeeping) 에 특화된 온라인 트랜잭션 처리(OLTP) 데이터베이스임
-
Viewstamped Replication(VR) 합의 프로토콜 기반의 strong serializability를 보장하며, 계좌와 계좌간 전송(transfer) 데이터만 저장
- 은행 내부 스위치, 중개업, 티켓 발권, 전력 계량 등 거래량이 많고 동시성 경쟁이 심한 환경에 적합함
- 단일 노드(Core)에서 모든 쓰기 연산을 관장하는 구조로 수평 확장(Scale-out)이 아니라 수직 확장(Scale-up)에 집중
- 배치 처리, IO 병렬화, 고정 스키마 등 하드웨어 친화적 최적화로 단일 노드 처리량 극대화를 지향함
장애 복원력 및 결함 허용
- TigerBeetle은 메모리, 프로세스, 시계, 저장소, 네트워크 결함에 대해 명시적 모델 및 복구 절차 제공
- 데이터 내구성은 단 하나의 복제본만 살아 있어도 데이터 손실이 없음을 보장
- 모든 복제본에서 기록이 손상되면 안전하게 멈추는 형태
- 시스템 하드웨어/소프트웨어 장애, 시계 오차, 디스크 손상, 네트워크 지연·손실·중복 등 다양한 장애를 가정
-
Viewstamped Replication과 Protocol-Aware Recovery 기법, 데이터 블록 체크섬 및 다중 복제본 저장 적용
-
런타임 검증(assertion) 활용해 오류 및 버그 발생 시 피해를 최소화함
업그레이드 방식
- 바이너리에는 현재 버전과 여러 이전 버전의 코드가 포함되어 있음
- 업그레이드는 단순히 바이너리를 교체하는 것만으로 가능
- 클러스터 내 모든 노드가 자동 롤링 방식으로 버전 변경, 사용자 개입 최소화
- 특정 버전에서 커밋된 연산이 다른 버전에서 중복 커밋되는 것을 방지하여 상태 불일치 방지에 유리함
시간 모델
-
VR 뷰와 연산 번호를 이용한 논리 시계와, 하이브리드 물리 시계(physical time) 동시 사용
- 리더가 모든 복제본의 POSIX 시각 수집, 오차 범위 내에서 클러스터 상호 동기화
- 시계 동기화가 60초 이상 실패하면 서비스 거부
- 타임스탬프는 "유닉스 에폭 이후 나노초" 단위지만 실제 POSIX 시간과 27초 오차 발생
- 윤초나 음의 시간 조정 시 내부 시계가 느려지는 현상 있음
데이터 모델
-
계정(account) 과 이체(transfer) 라는 두 가지 데이터 타입만 지원
- 각 필드는 고정 크기, 불변성(immutable) 원칙, unsigned int 기반 설계
- 계정은 사용자 정의 128비트 id, 원장(ledger), 플래그, 생성 시각, 커스텀 필드로 정의
- 이체는 debit/credit account id, code, amount, 커스텀 필드 등 포함
- 이체는 즉시 수행(단일 단계) 또는 2단계(예약·실행 협상) 처리 모두 지원
- 예약 전송(pending) 취소/만료 가능
- 특수 이체로 계좌 폐쇄/재개 처리 가능
연산 모델 및 트랜잭션
- 클라이언트가 데이터 상태 갱신 또는 조회를 위한 단일 요청(batch) 단위로 동작
- 요청 내 각 이벤트는 순차적이고 원자적(atomic) 트랜잭션으로 처리
- 반복 실행, 다중 요청 트랜잭션, 대화형 쿼리 등은 지원하지 않음
-
강한 일관성(Strong Serializability) 및 강한 세션 일관성 제공
- 각 연산의 성공·실패, 오류코드 반환, 체인(Chain, 서브트랜잭션) 기능을 통한 복합 처리 지원
Jepsen 테스트 설계
- Jepsen 라이브러리 통한 속성 기반(property-based) 테스트와 장애 주입(fault injection) 수행
- LXC, EC2 등 다양한 환경에서 3~6노드 클러스터 대상으로 실험
- 데이터 모델 제약으로 기존 리스트·셋 형태 일관성 검증 어려움 → 전체 연산 순서(total order) 이용해 상태/시간 일관성 검증
- 타임스탬프 기반 일관성 체크, 모델 검증, 시뮬레이션 등 서로 보완적 방식으로 오류 감지
모델 검증과 연산 생성
-
1600+ 라인 규모의 단일 스레드 상태 기계 모델로 TigerBeetle 동작 정확성 세밀하게 확인
- 다양한 오류 조건(중복 id, 불연속 타임스탬프, 잔고 제약 등)와 링크드 체인에 대한 추론 및 롤백 처리
- 검증 효율성을 위해 operation·id 생성, 상태 업데이트, 확률 기반 쿼리 조합 등 다양한 방식 활용
장애 주입
- 프로세스 크래시(SIGKILL), 일시정지(SIGSTOP), 네트워크 파티션, 클럭 변경 등 기본 장애 시나리오 포함
- 버전 업그레이드, 파일 손상 시뮬레이션, 일부 복제본만 부분 손상 등 세밀한 저장소 장애 주입
- 지그재그(helical) 디스크 손상 등 다양한 시나리오로 데이터 손실 가능성 최소화 검증
주요 버그 사례 및 개선 내역
요청 타임아웃 처리의 문제점 (#206)
- TigerBeetle 설계상 클라이언트 요청이 절대로 타임아웃되지 않음; 클러스터로부터 응답받을 때까지 무한 재시도
- 실제로는 Java 등 클라이언트가 비동기 연산시 타임아웃 예외를 발생할 수 있으며, 애플리케이션에서 외부 타임아웃을 둘 수밖에 없음
- 네트워크 오류나 확실한 오류를 애매하게 숨기는 설계로 인해 명확한 실패와 불확실 오류 구분이 어려움
- Jepsen은 실패 유형(확실/불확실)별 반환 방식 및 재시도 옵션 추가를 권고
클라이언트 오류로 인한 JVM 크래시 (#2435)
- 타임아웃을 우회하기 위한 스레드/비동기 래핑이 JVM segfault 문제를 유발
- Java 클라이언트에서 적절히 초기화되지 않은 필드가 참조되어 발생, 0.16.12에서 픽스
세션 만료시 클라이언트 크래시 (#2484)
- 과도한 세션으로 인한 클라이언트 강제 종료 현상
- 0.16.13부터 오류 반환식으로 개선
단일 노드 장애시 대기 시간 급등 (#2739)
- 링 기반 복제 방식의 약점으로 일부 노드 실패시 전체 응답 시간이 극심하게 늘어남
- 원인: 기본적으로 프라이머리가 다음 노드로 한 단계씩 메세지를 보내는데, 일부 노드 실패시 ack 미수신으로 대기 발생
- 0.16.30 이후, 역방향 복제 및 동적 링 토폴로지 등 도입해 장애 시 응답 지연 대폭 개선
Java 클라이언트 Header API 버그 (#2495)
- 빈 응답 배치에 singleton 객체 사용하여 헤더·타임스탬프가 잘못 공유되는 문제 발생
- 데이터 정확성에는 영향 없으나 헤더 API 결과가 오염됨, 0.16.14에서 수정
쿼리 결과 누락 (#2544)
- 0.16.13 버전 query_accounts, query_transfers 등 결과 일부 누락되는 버그 보고, 응답 결과가 올바른 prefix로만 제한됨
결론
- TigerBeetle은 금융·회계 분야에서 높은 안전성과 결함 허용성을 요구하는 환경에 특화됨
- Jepsen 시리즈 테스트로 다양한 복원력, 일관성, 연산 모델, 성능 이슈가 드러남
- 적극적 협업을 통해 장애 복원력, 클라이언트 오류 처리, 복제 및 업그레이드 자동화 등 실질적인 개선 이뤄짐
- 최신 버전에서 더욱 견고한 장애 대응, 연결·응답 보장, 연산 일관성 등 높은 수준의 신뢰성 제공
(이 내용의 일부는 Github, 공식 TigerBeetle 문서, Jepsen 테스트 리포트 등 다양한 오픈 소스를 참고하여 작성됨)