서버 시스템을 개발할 때 크고 동시 데이터 요청에 적응하기 위해서는 특히 분산 시스템에서 작업 할 때 데이터를 비동기 적으로 저장해야합니다. 현재 삽입 데이터베이스가 자동 ID를 검색 할 때까지 기다릴 수 없습니다. 대신 글로벌 고유 ID를 사용하여 데이터베이스를 삽입하기 전에 글로벌 고유 ID를 생성해야합니다. 게임 서버에서 글로벌 고유 ID는 미래의 서버 조합에 사용될 수 있으며 주요 충돌은 없습니다. 앞으로 비즈니스 성장의 경우 데이터베이스 및 분할 테이블을 구현할 수 있습니다. 예를 들어, 사용자의 항목은 동일한 샤드에 배치해야 하며이 샤드는 사용자 ID의 범위 값, 예를 들어 사용자 ID가 1000보다 크고 샤드에서 10000보다 작습니다. 현재 다음은 일반적으로 사용됩니다.
1. Java 자신의 uuid.
uuid.randomuuid (). toString ()은 서비스 프로그램을 통해 로컬로 생성 될 수 있으며 ID 생성은 데이터베이스의 구현에 의존하지 않습니다.
장점 :
로컬로 ID를 생성하고 원격 통화가 필요하지 않습니다.
세상은 반복하지 않는 유일한 세상입니다.
수평 확장 능력은 매우 좋습니다.
단점 :
ID에는 128 비트가있어 넓은 공간을 차지하고 문자열 유형으로 저장해야하며 인덱싱 효율은 매우 낮습니다.
생성 된 ID에는 타임 스탬프가 포함되어 있지 않으며 추세는 증가 할 수 없습니다. 데이터베이스 데이터베이스를 나눌 때 의존하기가 어렵습니다.
2. REDIS 기반 릭 방법
Redis 자체는 단일 스레드로 작동되며, 점점은 원자 적으로 증가한 작업을 보장합니다. 또한 증분 단계 크기 설정을 지원합니다.
장점 :
배포하기 쉽고 사용하기 쉽습니다. Redis API 만 호출하면됩니다.
여러 서버가 공유 데이터의 개발 시간을 줄이기 위해 REDIS 서비스를 공유 할 수 있습니다.
Redis는 단일 고장 지점의 문제를 해결하기 위해 클러스터에 배치 할 수 있습니다.
단점 :
시스템이 너무 크면 동시에 Redis에 대한 여러 서비스 요청이 성능 병목 현상을 유발합니다.
3. Flicker의 솔루션
이 솔루션은 ID를 생성하기 위해 특별히 별도의 데이터베이스를 사용하는 데이터베이스의 자동 증가 ID를 기반으로합니다. 온라인에서 세부 정보를 찾을 수 있습니다. 나는 개인적으로 사용하는 것이 매우 번거 롭다고 생각하며 그것을 사용하는 것이 권장되지 않습니다.
4. 트위터 눈송이
Snowflake는 트위터의 오픈 소스 인 분산 ID 생성 알고리즘입니다. 핵심 아이디어는 41 비트를 밀리 초 수로, 기계 번호로 10 비트, 12 비트를 밀리 초 내의 일련 번호로 사용하는 긴 유형 ID를 생성하는 것입니다. 이 알고리즘은 기계 당 최대 1,000*(2^12)의 ID를 이론적으로 생성 할 수 있으며, 이는 약 400W이며 비즈니스의 요구를 완전히 충족시킬 수 있습니다.
Snowflake 알고리즘의 아이디어에 따르면 비즈니스 시나리오를 기반으로 자체 고유 한 ID를 생성 할 수 있습니다. Java의 긴 유형의 길이는 64 비트이므로 우리가 디자인 한 ID는 64 비트로 제어해야합니다.
장점 : 고성능, 낮은 대기 시간; 독립적 인 응용 프로그램; 시간이 지남에 따라.
단점 : 독립적 인 개발 및 배포가 필요합니다.
예를 들어, 우리가 디자인 한 ID에는 다음 정보가 포함되어 있습니다.
| 41 비트 : 타임 스탬프 | 3 비트 : 면적 | 10 비트 : 기계 번호 | 10 비트 : 일련 번호 |
고유 한 ID를 생성하는 Java 코드 :
/*** 사용자 정의 ID 생성기* ID 생성 규칙 : ID 최대 64 비트 ** | 41 비트 : 타임 스탬프 (MS) | 3 비트 : 지역 (컴퓨터 실) | 10 비트 : 기계 번호 | 10 비트 : 일련 번호 |*/public class gameuuid {// 참조 시간 프라이빗 롱 트윈 치크 = 1288834974657L; // THU, 04 2010 년 4 월 4 일 01:42:54 GMT // 지역 플래그 숫자 개인 최종 정적 긴 grealIDBITS = // 기계 식별 숫자 개인 최종 정적 긴 WorkerIdbits = 10L; // 일련 번호 숫자 개인 정적 최종 롱 시퀀스 비트 = 10L; // 영역 ID 개인 최종 정적 최대 maxREGEID = -1L ^ (-1L); 기계 ID 개인 최종 정적 최종 MaxWorkerid = -1l ^ (-1L << workerIdbits); // 일련 번호 ID의 최대 값 개인 최종 최종 최종 정적 긴 시퀀스 마스크 = -1l ^ (-1L << 시퀀스 비트); // 기계 ID는 왼쪽 개인 정적 긴 작업자로 10 비트로 이동합니다. Long regionIdshift = equenceBits + workerIdbits; // 시간은 23 비트로 왼쪽으로 이동합니다. 비공개 최종 최종 정적 긴 타임 스탬프 히프트 = 시퀀스 비트 + workerIdbits + grealIdbits; 비공개 정적 Long LastTimestamp = -1L; 비공개 긴 시퀀스 = 0L; 개인 최종 긴 직원; 개인 최종 Long RegionId; 공개 gameUuid (긴 Workerid, Long regionId) {// 범위를 벗어난 경우 (Workerid> maxworkerid || workerid <0) { "Throw New ImperalargumentException ("Worker ID는 %D 또는 LEC보다 0보다 클 수 없습니다 "); %d 이하 0 ");} this.workerid = workerid; this.regionId = greatId;} public gameUuid (long workerid) {// 범위에서 벗어난 경우 (Workerid> maxWorkerId || workerid <0) { "Worker ID는 %d 또는 0보다 클 수 없습니다"); this.nextid (false, 0);}/*** @param ispadding* @param busid* @return*/private synchronized long nextid (boolean ispadding, long busid) {long timestamp = timegen (); long paddingnum = greaid; if (ispadding) {paddingnum = bustim; if (timestpam); {새로운 예외 ( "시계가 뒤로 이동했습니다." + (lasttimestamp -timestamp) + "millioneconds")에 대한 ID를 생성하는 것을 거부합니다. 시퀀스는 10 비트에 불과하기 때문에 시퀀스 마스크와 결합되어 고 비트 시퀀스 = (시퀀스 + 1) 및 시퀀스 세미 마스크; // 오버플로 여부, 즉 모든 밀리 초에서 1024를 초과합니다. 1024 일 때, 그것은 시퀀스 마스크와 결합되며, 시퀀스는 0if (시퀀스 == 0) {// 다음 밀리 초 타임 스탬프 = tailnextmillis (lasttimestamp)까지 대기합니다. // Mantissa가 더 임의적인지 확인하기 위해 마지막 비트 시퀀스에서 임의의 숫자를 설정합니다. = New Securerandom (). NextInt (10);} lasttimestamp = timestamp; return ((timestamp -Twepoch) << timestampleftshift) | (PaddingNum << greaIDShift) | (Workerid << workeridshift) | 시퀀스;} // 이전 시간보다 작고 (NTP 콜백과 같은 문제로 인해) 생성 시간이 점진적 트렌드를 유지하고, 긴 tailnextmillis (Final Long Lasttimestamp) {long timestamp = this.timegen (); TimeGen () {return System.CurrentTimeMillis ();}}사용자 정의 방법을 사용할 때 주목해야 할 사항 :
성장 추세를 유지하기 위해서는 일부 서버의 시간을 일찍 그리고 일부 서버의 늦게까지 피해야하므로 모든 서버의 시간을 제어해야하며 NTP 시간 서버가 서버로 돌아 오는 시간을 피해야합니다. 밀리 초를 건너면 일련 번호는 항상 0에 도달하여 일련 번호 0으로 더 많은 ID를 만들어 모듈로 잉 후 ID가 고르지 않으므로 일련 번호는 매번 0에 속하지 않고 0에서 9까지의 임의 숫자입니다.
우리는 우리의 요구에 따라 위에서 언급 한 방법을 선택할 수 있습니다. 게임 서버 개발에서는 모바일 게임과 같은 자신의 게임 유형에 따라 선택할 수 있으며 간단하고 실수가 쉽지 않은 간단한 Redis 메소드를 사용할 수 있습니다. 이러한 종류의 게임에서 단일 서버에서 생성 된 새 ID 수는 너무 크지 않기 때문에 요구 사항을 완전히 충족시킬 수 있습니다. 대형 세계 게임 서버의 경우 주로 배포되므로 눈송이를 사용할 수 있습니다. 위의 눈송이 코드는 예제 일 뿐이며 필요에 따라 사용자 정의해야하므로 추가 개발량이 있으므로 위의 예방 조치에주의를 기울여야합니다.
위는 Java 코드를 사용하여 Java 코드를 기반으로 글로벌 고유 ID를 생성하기 위해 게임 서버를 구현하기 위해 Java 코드를 사용하는 방법에 대한 요약입니다. 모든 사람에게 도움이되기를 바랍니다. 궁금한 점이 있으면 메시지를 남겨 주시면 편집자가 제 시간에 모든 사람에게 답장을 드리겠습니다. Wulin.com 웹 사이트를 지원해 주셔서 대단히 감사합니다!