데이터베이스 클러스터에서 id 의 고유성을 보장하는 방법, 초당 20 만 개의 동시 이벤트가 있다고 가정합니다.
소포? 실체
수입? Java.lang.management.management factory;
수입? Java.net.inetaddress;
수입? Java.net.network interface;
/* *
*? & LTP> 이름: idworker.java
*? & LTP> 설명: 분산 자체 성장 ID
*? & ltpre & gt
*? 트위터? 눈송이 자바 구현 시나리오
*? & lt/pre & gt;;
*? 핵심 코드는 해당 ID 작업자 클래스에 대해 구현되며 원리 구조는 다음과 같습니다. 저는 0 을 사용하여 비트를 나타내고,-를 사용하여 각 부분의 기능을 구분합니다.
*? 1||0-0000000000? 0000000000? 0000000000? 0000000000? 0? -응? 00000? -00000 이요? -000000000000
*? 위 문자열에서 첫 번째 비트는 사용되지 않고 (실제로 long 의 기호 비트로도 사용 가능), 다음 4 1 비트는 밀리초 시간입니다.
*? 그런 다음 5 비트 데이터 센터 식별 비트, 5 비트 시스템 ID (식별자가 아니지만 실제로는 스레드 ID) 가 있습니다.
*? 그러면 현재 밀리초의 12 비트 수를 합치면 64 비트에 불과하며 긴 유형이다.
*? 이렇게 하면 전체 시스템이 시간순으로 정렬되고 전체 분산 시스템에서 ID 충돌 (데이터 센터와 시스템 ID 구분) 이 발생하지 않는다는 장점이 있습니다.
*? 매우 효율적입니다. 테스트를 거쳐 눈송이는 초당 약 26 만 개의 ID 를 생성하여 요구 사항을 완벽하게 충족합니다.
*? & LTP>
*? 64 비트 ID? (42 (밀리초) +5 (기계 ID)+5 (서비스 코드)+12 (반복 누적))
*
*? @ 저자? 폴 림
*/
공공? 반? Id 작업자? {
//? 시간 시작 마크 포인트는 일반적으로 시스템의 가장 늦은 시간을 기준으로 합니다 (일단 확인되면 변경할 수 없음).
개인? 결승전? 정전기? 용? Twepoch? =? 128834974657l;
//? 기계 식별 번호
개인? 결승전? 정전기? 용? 워릭비츠? =? 5L
//? 데이터 센터 식별 번호
개인? 결승전? 정전기? 용? 데이터 센터 id 비트? =? 5L
//? 최대 시스템 ID
개인? 결승전? 정전기? 용? MaxWorkerId? =? -1L? -응? (-1L? & lt& lt? 작업자 id 비트);
//? 최대 데이터 센터 ID
개인? 결승전? 정전기? 용? MaxDatacenterId? =? -1L? -응? (-1L? & lt& lt? Datacenteridbits);
//? 밀리초 단위의 자체 증가
개인? 결승전? 정전기? 용? SequenceBits? =? 12l;
//? 기계 ID 가 왼쪽으로 12 비트 이동합니다.
개인? 결승전? 정전기? 용? WorkerIdShift? =? SequenceBits
//? 데이터 센터 ID 왼쪽 17 비트.
개인? 결승전? 정전기? 용? 데이터 센터 IdShift? =? SequenceBits? +? 위키백과: 위키백과
//? 시간 밀리초가 왼쪽으로 22 비트 이동합니다.
개인? 결승전? 정전기? 용? TimestampLeftShift? =? SequenceBits? +? 워릭비츠? +? DatacenterIdBits
개인? 결승전? 정전기? 용? SequenceMask? =? -1L? -응? (-1L? & lt& lt? SequenceBits
/*? 마지막 프로덕션 id 타임스탬프? */
개인? 정전기? 용? Last 타임스탬프? =? -1l;
//? 0, 동시 제어
개인? 용? 시퀀스? =? 0l;
개인? 결승전? 용? 작업자 id
//? 데이터 id 섹션
개인? 결승전? 용? DatacenterId
공공? IdWorker(){
This.datacenterId? =? Getdata centerid (maxdata centerid);
This.workerId? =? Getmaxworkerid (데이터 센터, maxworkerid);
}
/* *
*? @param? 근로자 Id
* 작업자 ID
*? @param? 데이터 센터 Id
* 일련 번호
*/
공공? Id 작업자 (길이? 작업자 id,? 용? DatacenterId)? {
만약? (작업자 id? & gt? MaxWorkerId? | |? 작업자 id? & lt? 0)? {
던져? 새 것? Illegalargumentexception (string.format ("작업자? Id? 안 돼요? 그래요? 더 위대한가? 비교? %d? 아니면? 적게? 비교? 0 ",? MaxWorkerId)););
}
만약? (데이터 센터 Id? & gt? MaxDatacenterId? | |? 데이터 센터 Id? & lt? 0)? {
던져? 새 것? Illegalargumentexception (string.format ("데이터 센터? Id? 안 돼요? 그래요? 더 위대한가? 비교? %d? 아니면? 적게? 비교? 0 ",? MaxDatacenterId)););
}
This.workerId? =? 작업자 id
This.datacenterId? =? DatacenterId
}
/* *
*? 다음 ID 가져오기
*
*? @ 반환
*/
공공? 동기화? 용? NextId ()? {
용? 타임 스탬프? =? Timegen ();
만약? (타임 스탬프? & lt? LastTimestamp)? {
던져? 새 것? Runtimeexception (string.format ("clock? 감동? 뒤로. 거부? 어디 가? 생성? Id? 뭐 때문에? %d? 밀리초',? Last 타임스탬프? -응? 타임 스탬프));
}
만약? (lastTimestamp? = =? 타임 스탬프)? {
//? 현재 밀리 초 이내에+1
시퀀스? =? (시퀀스? +? 1)? & amp? SequenceMask
만약? (시퀀스? = =? 0)? {
//? 현재 밀리초 수가 꽉 차면 다음 초를 기다립니다.
타임 스탬프? =? Tilnextmillis (last timestamp);
}
}? 그렇지 않으면요? {
시퀀스? =? 0l;
}
Last 타임스탬프? =? 타임스탬프
//? ID 오프셋 조합은 최종 ID 를 생성하고 해당 ID 를 반환합니다.
용? NextId? =? ((타임 스탬프? -응? Twepoch)? & lt& lt? TimestampLeftShift)
|? (데이터 센터 Id? & lt& lt? 데이터 센터 IdShift)
|? (작업자 id? & lt& lt? WorkerIdShift)? |? 시퀀스;
반환? NextId
}
개인? 용? TilNextMillis (최종? 용? LastTimestamp)? {
용? 타임 스탬프? =? This.timegen ();
언제? (타임 스탬프? & lt=? LastTimestamp)? {
타임 스탬프? =? This.timegen ();
}
반환? 타임스탬프
}
개인? 용? TimeGen ()? {
반환? System.currenttimemillis ();
}
/* *
*? & LTP>
*? 알았어? MaxWorkerId
*? & lt/p & gt;;
*/
보호받고 있습니까? 정전기? 용? GetMaxWorkerId(long? 데이터 센터 Id,? 용? MaxWorkerId)? {
StringBuffer? Mpid? =? 새 것? Stringbuffer ();
Mpid.append (데이터 센터);
문자열? 이름? =? Managementfactory.getruntimemxbean () 을 참조하십시오. Getname ();
만약? (! Name.isEmpty ()? {
/*
*? 알았어? JvmPid
*/
Mpid.append (name.split ("@" [0]);
}
/*
*? 마이크. +? PID? 무슨 일이야? 하쉬코드? /kloc 가져오기-0/6 낮음
*/
반환? (mpid.toString (). HashCode ()? & amp? 0xffff)? %? (maxWorkerId? +? 1);
}
/* *
*? & LTP>
*? 데이터 id 섹션
*? & lt/p & gt;;
*/
보호받고 있습니까? 정전기? 용? GetDatacenterId(long? MaxDatacenterId)? {
용? Id? =? 0l;
해봐? {
인터넷 주소? Ip? =? Inetaddress.getlocalhost ();
네트워크 인터페이스? 인터넷? =? Networkinterface.getbyinetaddress (IP);
만약? (인터넷? = =? Null)? {
Id? =? 1l;
}? 그렇지 않으면요? {
Byte[]? 마이크. =? Network.gethardwareaddress ();
Id? =? ((0x000000FF? & amp? "용"? Mac[mac.length? -응? 1])
|? (0x0000FF00? & amp? ((길이)? Mac[mac.length? -응? 2])? & lt& lt? 8))? & gt& gt? 6;
Id? =? Id? %? (maxDatacenterId? +? 1);
}
}? 받아요? (예외? E)? {
System.out.println ("? GetDatacenterId:? " -응? +? E. getmessage ());
}
반환? Id;
}
공공? 정전기? 무효화? 메인 (string []? Args)? {
//Twitter 26 만 개의 고유 id
Id 작업자? Id 작업자? =? 새 것? Id 작업자 (0,0);
뭐 때문에? (int? 나? =? 0; -응? 나? & lt2600? 을 눌러 섹션을 인쇄할 수도 있습니다 -응? I++)? {
System.out.println (idworker.nextid ());
}
}
}