자바 알고리즘 정적 내부 클래스 눈꽃 알고리즘 구현
테이블 의 메 인 키 ID 를 생 성 할 때,우 리 는 메 인 키 가 증가 하거나 UUID 를 고려 할 수 있 지만,그것들 은 모두 뚜렷 한 단점 을 가지 고 있다
홈 키 자체 증가:1.자체 증가 ID 는 파충류 에 의 해 데 이 터 를 옮 겨 다 니 기 쉽다.2.분 표 라 이브 러 리 에서 ID 충돌 이 발생 합 니 다.
UUID:1.너무 길 고 색인 조각 이 있 으 며 색인 이 공간 을 많이 차지 하 는 문제 2.무질서 합 니 다.
눈꽃 알고리즘 은 분포 식 장면 에서 유일한 ID 를 만 드 는 데 적합 하 며 유일 하면 서도 정렬 할 수 있 습 니 다.눈꽃 ID 생산 효율 성 을 높이 기 위해 서 는
이 안에서 데이터 의 연산 은 모두 비트 연산 을 사용한다.
개념
1.원리
SnowFlake 알고리즘 이 ID 를 생 성 한 결 과 는 다음 그림 과 같은 64bit 크기 의 정수 입 니 다.
알고리즘 설명:
1bit 는 이 진 에서 가장 높 은 위 치 는 기호 위치 이 고 1 은 음 수 를 나타 내 며 0 은 정 수 를 나타 내기 때문이다.생 성 된 ID 는 모두 정수 이기 때문에 최고 위 는 0 으로 고정 되 어 있 습 니 다.
41bit-타임 스탬프 는 밀리초 단위 로 정확 하고 41 비트 의 길 이 는 69 년 동안 사용 할 수 있 습 니 다.시간 대 에 따라 정렬 할 수 있 는 중요 한 역할 도 있다.
10bit-작업 기계 id 10 비트 의 기계 표지,10 비트 의 길 이 는 최대 1024 개의 노드 배 치 를 지원 합 니 다.
12bit-시리 얼 번호,즉 일련의 자체 증가 id 로 같은 노드 가 같은 밀리초 에 여러 개의 ID 번 호 를 생 성 하 는 것 을 지원 할 수 있 습 니 다.
12 비트(bit)가 나 타 낼 수 있 는 최대 정 수 는 0,1,2,3,...4094 라 는 4095 개의 숫자 로 같은 기계 의 같은 시간 절단(밀리초)내 에 발생 하 는 4095 개의 ID 번 호 를 나 타 낼 수 있다.
자바 에서 64bit 의 정 수 는 log 형식 이기 때문에 자바 에서 SnowFlake 알고리즘 이 생 성 한 id 는 log 로 저장 된다 는 뜻 이다.
2.정적 클래스 클래스 단일 모드 에서 눈꽃 ID 코드 생산
아래 에 눈꽃 ID 를 생 성 하 는 코드 는 온라인 분포 식 프로젝트 에서 분포 식 메 인 키 ID 를 생 성 하 는 데 사용 할 수 있 습 니 다.디자인 이 사용 하 는 정적 내부 클래스 의 단일 모드 이기 때문에 synchronized 자 물 쇠 를 추가 하여 보장 합 니 다.
같은 서버 스 레 드 가 안전 합 니 다.서로 다른 서버 는 사실 상관 이 없다.그들의 기계 코드 가 일치 하지 않 기 때문에 같은 시각 에 두 서버 가 모두 눈꽃 ID 를 만들어 도 같 지 않다.
1.코드
public class SnowIdUtils {
/**
*
*/
private static class SnowFlake {
/**
* ( )
*/
private static final SnowIdUtils.SnowFlake SNOW_FLAKE = new SnowIdUtils.SnowFlake();
/**
*
*/
private final long START_TIMESTAMP = 1557489395327L;
/**
*
*/
private final long SEQUENCE_BIT = 12;
/**
*
*/
private final long MACHINE_BIT = 10;
/**
*
*/
private final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;
/**
* (4095)
*/
private final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
/**
* (1023)
*/
private final long MAX_MACHINE_ID = ~(-1L << MACHINE_BIT);
/**
* id
*/
private long machineIdPart;
/**
*
*/
private long sequence = 0L;
/**
*
*/
private long lastStamp = -1L;
/**
*
*/
private SnowFlake() {
//
long localIp = 4321;
//localIp & MAX_MACHINE_ID 1023, 12
machineIdPart = (localIp & MAX_MACHINE_ID) << SEQUENCE_BIT;
}
/**
* ID
*/
public synchronized long nextId() {
long currentStamp = timeGen();
//
while (currentStamp < lastStamp) {
// // ,ID .
throw new RuntimeException(String.format(" . Refusing to generate id for %d milliseconds", lastStamp - currentStamp));
}
if (currentStamp == lastStamp) {
// +1
sequence = (sequence + 1) & MAX_SEQUENCE;
//
if (sequence == 0) {
// ,
currentStamp = getNextMill();
}
} else {
// , 0
sequence = 0L;
}
lastStamp = currentStamp;
// + +
return (currentStamp - START_TIMESTAMP) << TIMESTAMP_LEFT | machineIdPart | sequence;
}
/**
* ,
*/
private long getNextMill() {
long mill = timeGen();
//
while (mill <= lastStamp) {
mill = timeGen();
}
return mill;
}
/**
*
*/
protected long timeGen() {
return System.currentTimeMillis();
}
}
/**
* long ID
*/
public static long uniqueLong() {
return SnowIdUtils.SnowFlake.SNOW_FLAKE.nextId();
}
/**
* String ID
*/
public static String uniqueLongHex() {
return String.format("%016x", uniqueLong());
}
/**
*
*/
public static void main(String[] args) throws InterruptedException {
//
long start = System.currentTimeMillis();
// 100
final CountDownLatch latch = new CountDownLatch(100);
// 20
final Map<Long, Integer> map = new ConcurrentHashMap();
for (int i = 0; i < 100; i++) {
// 100
new Thread(() -> {
for (int s = 0; s < 2000; s++) {
long snowID = SnowIdUtils.uniqueLong();
log.info(" ID={}",snowID);
Integer put = map.put(snowID, 1);
if (put != null) {
throw new RuntimeException(" ");
}
}
latch.countDown();
}).start();
}
// 100 ,
latch.await();
log.info(" 20 ID ={}", System.currentTimeMillis() - start);
}
}
2.테스트 결과그림 에서 우 리 는 얻 을 수 있다.
1.100 개의 스 레 드 와 동시에 20 만 개의 눈꽃 ID 를 생 성 하 는 시간 은 약 1.6 초 정도 이 고 모든 성능 은 만 ok 입 니 다.
2.20 만 개의 눈꽃 ID 를 생 성 하 는데 똑 같은 ID 가 하나 도 없습니다.왜냐하면 하나 가 있 으 면 이상 을 던 집 니 다.
3,왜 41 명 스탬프 최 장 69 년
우리 가 생각 하 는 41 의 2 진법 은 최대 치 인 41 위 가 모두 1 이다.즉,41 위 는 4.567916.밀리초 의 값 을 나 타 낼 수 있 고 단위 년 으로 바 뀌 면?
년
우 리 는 코드 를 불 려 서 알 수 있다.
public static void main(String[] args) {
//41
String minTimeStampStr = "00000000000000000000000000000000000000000";
//41
String maxTimeStampStr = "11111111111111111111111111111111111111111";
// 10
long minTimeStamp = new BigInteger(minTimeStampStr, 2).longValue();
long maxTimeStamp = new BigInteger(maxTimeStampStr, 2).longValue();
//
long oneYearMills = 1L * 1000 * 60 * 60 * 24 * 365;
//
System.out.println((maxTimeStamp - minTimeStamp) / oneYearMills);
}
실행 결과그 러 니까 눈꽃 알고리즘 으로 생 성 된 ID 는 69 년 동안 중복 되 지 않 을 수 있 습 니 다.69 년 이 넘 으 면 서버 배 치 를 바 꾸 는 것 도 고려 해 보 세 요.그리고 이 서버 의 ID 와 이전 에는 중복 되 지 않 았 음 을 보증 해 야 합 니 다.
이상 은 자바 알고리즘 의 정적 내부 클래스 가 눈꽃 알고리즘 을 실현 하 는 상세 한 내용 입 니 다.자바 알고리즘 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.