대규모 분산 환경에서 고유한 ID 생성
소개하다.
최근 작업 중에, 우리는 분포식 시스템에서 유일한 ID를 생성하는 방법을 찾고 있으며, 이 ID는 MySQL 테이블의 메인 키로도 사용할 수 있다.
우리는 MySQL 데이터베이스에서 우리는 간단하게 자동 증량 ID를 메인 키로 사용할 수 있지만, 이것은 블록을 나누는 MySQL 데이터베이스에서는 통하지 않는다는 것을 안다.
그래서 저는 다양한 기존 해결 방안을 연구했고 최종적으로 간단한 64개의 유일한 ID 생성기를 이해했습니다.
UUID를 사용하지 않는 이유는 무엇입니까?🤔
UUID는 전역에서 유일하게 128비트 16진수입니다.동일한 UUID가 두 번 생성될 가능성은 희박합니다.
UUID의 문제는 크기가 매우 크고 색인이 좋지 않다는 것입니다.데이터 집합이 증가할 때 인덱스 크기도 증가하고 조회 성능도 떨어진다.
UUID의 또 다른 문제는 사용자 환경과 관련이 있습니다.최종적으로, 우리 사용자는 유일한 표지부를 필요로 할 것이다.한 고객이 고객 서비스부에 전화를 걸어 표지부를 제공해 달라고 요구하는 것을 상상해 보세요.전체 UUID를 철자로 써야 하는 것은 즐거운 경험이 아닙니다.
트위터 눈꽃❄
트위터 snowflake는 트위터 내 객체(예: 트윗, 직접 메시지, 목록 등)에 대한 분산 계산에 사용되는 64비트 고유 식별자를 생성하는 전용 서비스입니다.
이러한 ID는 시간에 기반한 고유한 64비트 부호 없는 정수입니다.전체 ID는 다음 구성 요소로 구성됩니다.
UUID는 전역에서 유일하게 128비트 16진수입니다.동일한 UUID가 두 번 생성될 가능성은 희박합니다.
UUID의 문제는 크기가 매우 크고 색인이 좋지 않다는 것입니다.데이터 집합이 증가할 때 인덱스 크기도 증가하고 조회 성능도 떨어진다.
UUID의 또 다른 문제는 사용자 환경과 관련이 있습니다.최종적으로, 우리 사용자는 유일한 표지부를 필요로 할 것이다.한 고객이 고객 서비스부에 전화를 걸어 표지부를 제공해 달라고 요구하는 것을 상상해 보세요.전체 UUID를 철자로 써야 하는 것은 즐거운 경험이 아닙니다.
트위터 눈꽃❄
트위터 snowflake는 트위터 내 객체(예: 트윗, 직접 메시지, 목록 등)에 대한 분산 계산에 사용되는 64비트 고유 식별자를 생성하는 전용 서비스입니다.
이러한 ID는 시간에 기반한 고유한 64비트 부호 없는 정수입니다.전체 ID는 다음 구성 요소로 구성됩니다.
첫 번째 구성 요소로 시간 스탬프를 사용하기 때문에 시간 정렬도 가능합니다.또 다른 장점은 고가용성이다.
기본적으로 64비트 무기호 정수 (long) 는 길이가 19인 Id를 생성하지만, 때로는 너무 길 수도 있습니다. 우리의 용례는 길이가 10보다 크지 않아야 합니다.
본고는 unique ID generator의 간략한 버전을 공유합니다. 트위터 눈꽃 서비스에서 개술한 개념을 바탕으로 분포식 환경에서 유일한 ID를 생성하는 모든 용례에 적용됩니다.
인코딩 시간⌚
우리의 예에서 전체 ID는 스탬프 20개, 작업 번호 5개, 일련 번호 6개로 구성됩니다.
나머지 1은 항상 0으로 설정하여 최종값을 양수로 설정합니다.
Google 마이크로서비스는 이 랜덤 생성기를 사용하여 ID를 독립적으로 생성할 수 있습니다.이것은 효율적이고 int
크기(4바이트 또는 32비트)에 적합하다.
다음은 전체 Java 코드code credits-
단계 1 - 각 구성 요소에 필요한 자릿수를 초기화합니다.
public class Snowflake {
// Sign bit, Unused (always set to 0)
private static final int UNUSED_BITS = 1;
private static final int EPOCH_BITS = 20;
private static final int NODE_ID_BITS = 5;
private static final int SEQUENCE_BITS = 6;
private static final int maxNodeId = (int)(Math.pow(2, NODE_ID_BITS) - 1);
private static final int maxSequence = (int)(Math.pow(2, SEQUENCE_BITS) - 1);
// Custom Epoch (Fri, 21 May 2021 03:00:20 GMT)
private static final int DEFAULT_CUSTOM_EPOCH = 1621566020;
private volatile int lastTimestamp = -1;
private volatile int sequence = 0;
// Class Constructor
public Snowflake() {
this.nodeId = createNodeId();
this.customEpoch = DEFAULT_CUSTOM_EPOCH;
}
Here, we are taking custom epoch as of Fri, 21 May 2021 03:00:20 GMT.
EPOCH_BITS
는 20비트가 되고 현재 타임 스탬프를 초 단위로 채웁니다(초당 여러 개의 요청이 있을 수도 있고 밀리초를 사용할 수도 있습니다).NODE_ID_BITS
는 5비트이며 Mac 주소로 채워집니다.SEQUENCE_BITS
는 6비트로 로컬 카운터로 0에서 63까지 시작하여 0으로 리셋됩니다.
2단계 - ID를 생성하기 위한 함수를 생성synchronized
합니다.
public synchronized int nextId() {
int currentTimestamp = (int) (Instant.now().getEpochSecond() - customEpoch);
if(currentTimestamp < lastTimestamp) {
throw new IllegalStateException("Invalid System Clock!");
}
lastTimestamp = currentTimestamp;
return currentTimestamp << (NODE_ID_BITS + SEQUENCE_BITS) | (nodeId << SEQUENCE_BITS) | sequence;
}
잠깐만, 우리는 왜 이런 좌회전 & 논리 또는 조작을 해야 합니까?
정수가 32비트로 표시되고 처음에는 0으로 설정되어 있기 때문이다.
이 위치를 채우기 위해서, 우리는 각각 분량을 가져와야 하기 때문에, 우선 역원 시간 스탬프를 가져와, 5+6, 즉 왼쪽으로 11자리로 이동해야 한다.이렇게 하면 첫 번째 컴포넌트로 첫 번째 21위를 채웁니다(첫 번째 컴포넌트는 항상 0으로 설정되어 총 수를 플러스로 설정됨).나머지 11자리는 여전히 0이기 때문에 우리는 논리OR에 대해 다시 한 번 같은 일을 반복하고 다른 두 구성 요소도 마찬가지로 모든 32자리를 채워 완전한 숫자를 형성한다.
3단계 - 시스템 MAC 주소를 사용하여 노드 id를 생성하는 데 유용한 기능:
private int createNodeId() {
int nodeId;
try {
StringBuilder sb = new StringBuilder();
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
byte[] mac = networkInterface.getHardwareAddress();
if (Objects.nonNull(mac))
for(byte macPort: mac)
sb.append(String.format("%02X", macPort));
}
nodeId = sb.toString().hashCode();
} catch (Exception ex) {
nodeId = (new SecureRandom().nextInt());
}
nodeId = nodeId & maxNodeId;
return nodeId;
}
}
그것은 어떻게 일합니까?💡
이제 하나의 예를 통해 그것의 작업 원리를 이해합시다 -
지금이 태양이라고 가정하면 2021년 5월 23일 그리니치 표준시 00:00.이 특정 시간의 역원 시간 스탬프는 1621728000이다.
우선, 우리는 맞춤형 역원에 따라 시간 스탬프를 조정한다-
currentTimestamp=1621728000-162156620=161980(사용자 정의 역원에 따라 조정)
따라서 우리의 ID를 시작하기 위해 ID의 첫 20위(기호 위치가 있는 후)는 역원 시간 스탬프로 채워집니다.왼쪽으로 이동해서 이 값을 계산합시다.id = currentTimestamp << (NODE_ID_BITS + SEQUENCE_BITS )
다음은 구성된 노드 ID/shard ID를 가져와 다음 10자리를 채웁니다.id = id | nodeId << SEQUENCE_BITS
마지막으로, 우리는 자동으로 점차적으로 증가하는 서열의 다음 값을 가져와, 나머지 6자리를 채운다 -id = id | sequence // 6149376
이것이 우리의 최종 신분증이다🎉
이렇게!우리 프로그램에서 유일한 키야!
요약📊
본고는 길이>=7과 <=10의 눈꽃 id를 어떻게 생성하는지 간단한 해결 방안을 보여 줍니다.
참고로 세 개의 구성 요소의 위치 계수를 조절해서 작업에 적응할 수 있습니다.
참고:
생성기를 하나의 예로 유지해야 합니다. 이것은 모든 노드에 SequenceGenerator의 단일 실례만 만들어야 한다는 것을 의미합니다.없으면 중복 ID가 생성될 수 있습니다.
트위터는 뿐만 아니라 디스코드도 눈송이를 사용했다. 이들의 시대는 2015년 1초로 정해졌다.
인스타그램은 타임 스탬프 41자리, 조각 ID 13자리, 일련 번호 10자리 등 이 포맷의 수정 버전을 사용했다.
나는 이것이 너에게 도움이 되기를 바란다.감사합니다:)
인터넷 개발부터 하고 싶어요?결산하다▶ HTML 반응:최종 가이드
이 전자책은 대량의 간단하고 알기 쉬운 예와 검증된 노선도를 통해 인터넷 개발자가 되기 위해 알아야 할 모든 것을 가르치는 전면적인 지침서이다
포함👇
✅ 단도직입적 해석
✅ 간단한 코드 예
✅ 50개 이상의 흥미로운 프로젝트 아이디어
✅ 3. 비밀 자원 리스트
✅ 별도의 면접 준비
너는 심지어 체크아웃할 수 있다a free sample from this book
네가 직접 사고 싶다면, 이것은 책 한 권link이다.
원래 가격은 40달러이지만 이 링크의 가격은 16달러(원래 가격보다 60% 낮음)😉
👇
Reference
이 문제에 관하여(대규모 분산 환경에서 고유한 ID 생성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/apoorvtyagi/generating-unique-ids-in-a-large-scale-distributed-environment-257d
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
public class Snowflake {
// Sign bit, Unused (always set to 0)
private static final int UNUSED_BITS = 1;
private static final int EPOCH_BITS = 20;
private static final int NODE_ID_BITS = 5;
private static final int SEQUENCE_BITS = 6;
private static final int maxNodeId = (int)(Math.pow(2, NODE_ID_BITS) - 1);
private static final int maxSequence = (int)(Math.pow(2, SEQUENCE_BITS) - 1);
// Custom Epoch (Fri, 21 May 2021 03:00:20 GMT)
private static final int DEFAULT_CUSTOM_EPOCH = 1621566020;
private volatile int lastTimestamp = -1;
private volatile int sequence = 0;
// Class Constructor
public Snowflake() {
this.nodeId = createNodeId();
this.customEpoch = DEFAULT_CUSTOM_EPOCH;
}
Here, we are taking custom epoch as of Fri, 21 May 2021 03:00:20 GMT.
public synchronized int nextId() {
int currentTimestamp = (int) (Instant.now().getEpochSecond() - customEpoch);
if(currentTimestamp < lastTimestamp) {
throw new IllegalStateException("Invalid System Clock!");
}
lastTimestamp = currentTimestamp;
return currentTimestamp << (NODE_ID_BITS + SEQUENCE_BITS) | (nodeId << SEQUENCE_BITS) | sequence;
}
private int createNodeId() {
int nodeId;
try {
StringBuilder sb = new StringBuilder();
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
byte[] mac = networkInterface.getHardwareAddress();
if (Objects.nonNull(mac))
for(byte macPort: mac)
sb.append(String.format("%02X", macPort));
}
nodeId = sb.toString().hashCode();
} catch (Exception ex) {
nodeId = (new SecureRandom().nextInt());
}
nodeId = nodeId & maxNodeId;
return nodeId;
}
}
Reference
이 문제에 관하여(대규모 분산 환경에서 고유한 ID 생성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/apoorvtyagi/generating-unique-ids-in-a-large-scale-distributed-environment-257d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)