개요
Orders 테이블에 order_id 컬럼을 order_no 컬럼으로 변경하면서,
PK 생성 방식을 AUTO_INCREMENT에서 다른 방식으로 변경이 필요했다.
스노우플레이크 알고리즘을 선택한 이유
- 분산 환경에서 장점이 있는 알고리즘
스노우플레이크 알고리즘은 분산 환경에서 고유한 ID를 생성하는 데 최적화된 알고리즘이다.
우리 프로그램은 단일 서버에서 단일 스레드로 동작하는 구조라 분산 시스템은 아니지만,
적용해보며 학습하고 싶었다. - 가독성 문제
주문 목록 조회 API에서 주문번호를 유저가 직접 확인할 수 있도록 설계했다.
하지만 UUID(128비트)는 문자열 길이가 길어 가독성이 떨어지는 문제가 있어, 더 짧고 직관적인 ID가 필요했다. - DB에서 유리
UUID보다 짧은 길이를 가지므로 DB 저장 및 검색 성능에 유리하다.
데이터베이스 인덱싱 효율이 높아지고, bigint(64비트) 타입으로 저장할 수 있어 관리가 용이하다.
참고: https://f-lab.kr/insight/uuid-vs-snowflake-20241230
효율적인 주문 번호 생성: UUID와 스노우플레이크 알고리즘 비교
UUID와 스노우플레이크 알고리즘을 비교하여 효율적인 주문 번호 생성 방법을 탐구합니다. 각각의 장단점과 적용 사례를 통해 적합한 선택 기준을 제시합니다.
f-lab.kr
적용 방법
public class SnowflakeOrderNoGenerator {
private static final long epoch = 1740787200000L; // 2025-03-01 00:00:00 UTC
private static final long machineId = 0L; // 단일 서버
private static final long maxSequence = 4095; // 같은 밀리초에서 4096개 ID 생성 가능
private static long lastTimestamp = -1L; // 마지막으로 생성한 타임 스탬프
private static long sequence = 0L; // 같은 밀리초에서 증가하는 시퀀스 값
public static synchronized long generateOrderNo() {
long currentTimestamp = System.currentTimeMillis();
if (currentTimestamp < lastTimestamp) {
throw new IllegalStateException("Clock moved backwards. Refusing to generate ID");
}
// 같은 밀리초인 경우 sequence 값 증가
if (currentTimestamp == lastTimestamp) {
sequence = (sequence + 1) & maxSequence;
if (sequence == 0) {
while (currentTimestamp <= lastTimestamp) {
currentTimestamp = System.currentTimeMillis();
}
}
} else {
sequence = 0;
}
lastTimestamp = currentTimestamp;
// 순차적이고 유일한 64비트 정수형 ID 생성
return ((currentTimestamp - epoch) << 22) | (machineId << 12) | sequence;
}
}
- 유일성 보장: ID를 69년(41비트) 동안 안전하게 사용할 수 있음
- 생성된 주문번호 예시: 917997178847232
catsriding | 다양한 유일 ID 생성 전략 비교 및 Snowflake 기반 기본키 도입하기
유일 ID 생성은 데이터 무결성뿐만 아니라 분산 환경에서의 안정성 확보와 대규모 배치 작업에서의 효율성을 위해 필수적입니다. 자동 증가 키 전략은 충돌 위험이 있고, UUID 방식의 기본키는 길
www.catsriding.com