[TSID] 분산환경 기본키 채번 전략
왜 기본키 채번에 대해서 알아보는 것일까?
현재 실무에서 새 프로젝트를 진행하게 되었고 기존 프로젝트에서의 불편함을 개선하고자 고민했던 경험을 공유한다.
일반적인 프로젝트에서는 PK
와 자동증가 값
을 활용한 기본키 생성 전략을 사용하며 이전 프로젝트에서도 활용중이다.
아래와 같은 이슈로 인해 결론부터 논하자면 TSID
를 사용하기로 결정했고 기본키 채번 사례와 장단점에 대해서 알아본다.
첫번째 이슈
프로젝트는 AWS에서 멀티 리전으로 구성되어 있으며 MSA 아키텍처
를 활용중이다. 따라서 국가별 도메인별 디비가 독립적으로 존재한다.
이때 매출 등으로 인한 통계자료를 전체 데이터베이스에서 추출해야 되는 상황에 놓였다.
스노우플레이크
를 활용하여 전체 디비를 하나로 데이터레이크를 구축할때 자주 문제가 되는 부분이 있다.
예를 들면 각 나라별 회원디비를 하나의 테이블로 통합할 경우 TABLE의 아이디값의 중복이슈가 발생하게 된다.
두번째 이슈
현재 이커머스 프로젝트에서 각 도메인 (정산, 주문) 등에서 스프링 배치를 활용하여 데이터 정합성 체크 및 데이터갱신을 진행중이다.
이때 대량데이터 등록을 위해 벌크연산(Bulk insert)를 사용중인데 Spring Data JPA
를 사용중인 경우 save는 Insert 합치기가 적용되지 않는다.
따라서 JdbcTemplate
와 같이 문자열 기반 네이티브 쿼리 방식으로 벌크연산을 사용중인 도메인 프로젝트가 대부분이다.
일반적으로 사용하는 Auto Increment 채번이 뭘까?
Auto Increment
다수의 클라이언트에서 디비에 유일성을 보장하는 PK(프라이머리 키)
를 값을 동시에 삽입할 경우 중복 된 값에 대해서는 사용할 수 없다.
따라서 중복 체크가 필요하게 되고 이는 성능 저하의 원인이 된다.
이를 해결하기 위해 DBMS에서 관리하는 자동증가값인 AUTO INCREMENT
를 사용한다.
Primary Key
보통 프로젝트에서의 모든 데이터의 저장공간은 RDB를 활용하게 된다.
그리고 DB TABLE의 특정 레코드를 식별하기 위해 모든 컬럼의 값을 결정하는 프라이머리키
를 사용한다.
그런데 왜 이런 PK
사용을 하는 것일까?
관계형 데이터베이스의 각 테이블 주문, 주문상품이 있다면 외래키를 사용해서 유일성을 보장하고 서로를 참조한다. 이때 외래키가 바로
인 것이다.PK
이는 DBMS에서 not null, unique 사용을 강제하기때문에 관리상 큰 이점이 있다.
분산환경 채번 사례는 어떤것이 있을까?
위 이슈를 해소할 방법이 있을까?
기본키 채번 전략 4가지를 통해 알아보고자 한다.
1. DB별로 PK생성 규칙을 나누기
DB서버 증설 및 삭제작업이 쉽지 않고 관리가 어렵다는 단점이 있다.
- PK시작값을 디비별로 다르게 사용하는 방법
- 갈레라 클러스터 처럼 PK증분 기준을 디비별로 다르게 가져가는 방법
2. 중앙화된 PK관리 서버 사용
SPOF
를 일으킬 수 있는 단점이 있다.
- 플리커처럼 자동증가값을 티켓 서버에서 채번하여 중앙화된 서버를 두고 사용
3. 대체키 생성 규칙 사용
채번 규칙 설계 및 유지보수가 필요하다.
- 문자열로 된 대체키로 중복되지 않는 식별자를 수동으로 생성해서 사용
4. 랜덤생성 키 사용
어플리케이션에서 유일키를 생성하기 때문에 확장과 성능적 이점이 있음
UUID, KUSID
- ID가 숫자형에 비해 데이터가 크고 ID를 시간순으로 정렬할 수 없어
DBMS
검색 성능저하의 단점이 있음
ULID, 인스타그램ID, 스노우플레이크, 타임플레이크
- 타임스탬프 기반으로, 대체키를 시간순으로 정렬하기 용이함
TSID (Time-Sorted Unique Identifier)
Twitter의 Snowflake](https://github.com/twitter-archive/snowflake/tree/snowflake-2010) 및 ULID Spec 의 아이디어를 결합
- 세대 시간별로 정렬
- 64비트의 정수로 저장
- 13자의 문자열로 저장
- 문자열 형식은 Crockford의 base32 로 인코딩
- 문자열 형식은 URL 안전하고 대소문자를 구분하지 않으며 하이픈이 없음
- UUID, ULID, KSUID보다 짧음
이슈를 해결하기 위한 결론은?
이슈와 아래 조건을 만족하는 채번전략인 TSID
를 채택하였고 분산환경에서 중복없이 사용됨을 확인하였고 아직까지는 큰 문제없이 사용중이다.
- 기존 소스코드 수정 영향도 최소화
- 단일 시스템에서도 활용가능
- 분산환경(각 리전별 도메인별 디비)에서 중복없이 사용 가능
- Spring Batch 에서 JPA사용시 대량 삽입 수행가능
- 키 생성 속도가 200(miliis) 내외
- DBMS에서의 정렬이점 활용 가능
- 병렬처리 및 동시성 보장