대규모 분산 환경에서 고유한 ID 생성

소개하다.


최근 작업 중에, 우리는 분포식 시스템에서 유일한 ID를 생성하는 방법을 찾고 있으며, 이 ID는 MySQL 테이블의 메인 키로도 사용할 수 있다.
우리는 MySQL 데이터베이스에서 우리는 간단하게 자동 증량 ID를 메인 키로 사용할 수 있지만, 이것은 블록을 나누는 MySQL 데이터베이스에서는 통하지 않는다는 것을 안다.
그래서 저는 다양한 기존 해결 방안을 연구했고 최종적으로 간단한 64개의 유일한 ID 생성기를 이해했습니다.

UUID를 사용하지 않는 이유는 무엇입니까?🤔


UUID는 전역에서 유일하게 128비트 16진수입니다.동일한 UUID가 두 번 생성될 가능성은 희박합니다.
UUID의 문제는 크기가 매우 크고 색인이 좋지 않다는 것입니다.데이터 집합이 증가할 때 인덱스 크기도 증가하고 조회 성능도 떨어진다.
UUID의 또 다른 문제는 사용자 환경과 관련이 있습니다.최종적으로, 우리 사용자는 유일한 표지부를 필요로 할 것이다.한 고객이 고객 서비스부에 전화를 걸어 표지부를 제공해 달라고 요구하는 것을 상상해 보세요.전체 UUID를 철자로 써야 하는 것은 즐거운 경험이 아닙니다.

트위터 눈꽃❄


트위터 snowflake는 트위터 내 객체(예: 트윗, 직접 메시지, 목록 등)에 대한 분산 계산에 사용되는 64비트 고유 식별자를 생성하는 전용 서비스입니다.
이러한 ID는 시간에 기반한 고유한 64비트 부호 없는 정수입니다.전체 ID는 다음 구성 요소로 구성됩니다.
  • 밀리초 단위의 역원 시간 스탬프 - 41비트(사용자 정의 역원에 비해 69년)
  • 구성된 기계/노드/슬라이스 Id-10비트(최대 210개, 1024개 Id)
  • 일련 번호 -12비트(기계당 로컬 카운터 1개, 4096개당 0으로 설정)
  • 처음에 1개의 보존 위치를 0으로 설정하여 총 수를 정수로 한다.

  • 첫 번째 구성 요소로 시간 스탬프를 사용하기 때문에 시간 정렬도 가능합니다.또 다른 장점은 고가용성이다.
    기본적으로 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% 낮음)😉


    👇

    좋은 웹페이지 즐겨찾기