Hi / Lo 알고리즘은 무엇입니까?


464

Hi / Lo 알고리즘은 무엇입니까?

나는이 발견 한 자 NHibernate (이, 고유 키를 생성하는 섹션 5.1.4.2 하나의 방법이다) 문서,하지만 난 그것을 작동하는 방법의 좋은 설명을 발견하지 않았습니다.

나는 Nhibernate가 그것을 처리한다는 것을 알고 있으며 내부를 알 필요는 없지만 단지 궁금합니다.

답변:


540

기본 아이디어는 기본 키를 구성 할 두 개의 숫자 ( "높은"숫자 및 "낮은"숫자)가 있다는 것입니다. 클라이언트는 기본적으로 "높은"시퀀스를 증가시킬 수 있으며 다양한 "낮은"값으로 이전 "높은"값의 전체 범위에서 키를 안전하게 생성 할 수 있다는 것을 알고 있습니다.

예를 들어, 현재 값이 35 인 "높은"시퀀스가 있고 "낮은"숫자가 0-1023 범위에 있다고 가정합니다. 그런 다음 클라이언트는 시퀀스를 36으로 늘리고 (35를 사용하는 동안 다른 클라이언트가 키를 생성 할 수 있도록) 키 35/0, 35/1, 35/2, 35/3 ... 35/1023이 모두 가능합니다.

기본 키가없는 값을 삽입 한 다음 클라이언트로 다시 가져 오는 대신 클라이언트 측에서 기본 키를 설정할 수 있으면 매우 유용 할 수 있습니다 (특히 ORM의 경우). 이외에도 다른 어떤에서, 당신이 쉽게 상위 / 하위 관계를 확인하고 당신이 전에 모든 장소에 키를 가질 수 있습니다 의미 있는 그들에게 간단한 일괄 처리하게 삽입.


14
"낮은 범위"는 클라이언트 내에서 조정되는 반면 "높은 시퀀스"는 DB 시퀀스에 해당합니까?
Chris Noe

14
hi & lo 값은 일반적으로 단일 정수 값으로 구성됩니까, 아니면 두 부분으로 된 비즈니스 키로 구성됩니까?
Chris Noe

51
IP 주소와 같은 경우-ICANN은 높은 '네트워크'번호를 제공하고, 주어진 CIDR 범위의 한계 내에서 원하는만큼 낮은 '호스트'번호를 갖습니다.
gbjbaanb

6
@Adam : 기본적으로 아무 것도 없습니다. 많은 키를 생성하는 것보다 하나의 값 ( "높은"부분)을 증가시키는 것이 잠재적으로 저렴합니다. ( 데이터 전송 측면에서 훨씬 저렴합니다. 최소한의 대역폭으로 많은 수의 키를 "예약"할 수 있습니다.)
Jon Skeet

4
@Adam : 키가 숫자 일 경우에 해당됩니다. GUID에는 그다지 많지 않습니다 :) 그러나 그렇습니다. 단순한 숫자의 경우 원자가 "고정 된 양만큼 증가"합니다. 하나의 숫자가 두 개의 섹션으로 나뉘어져 있다고 생각하면 그것은 실제로 안녕이하는 일입니다.
Jon Skeet

157

Jon의 답변 외에도

연결이 끊어진 상태에서 작업 할 수 있습니다. 그런 다음 클라이언트는 서버에 hi 숫자를 요청하고 lo 자체를 증가시키는 오브젝트를 작성할 수 있습니다. Lo 범위를 모두 사용할 때까지 서버에 접속할 필요가 없습니다.


1
나는 이것을 간결하게 선호합니다.
개발자 Marius Žilėnas 2016 년

34

이것은 매우 일반적인 질문 이므로이 답변을 기반으로하는이 기사를 작성 했습니다.

hi / lo 알고리즘은 시퀀스 도메인을 "hi"그룹으로 분할합니다. "hi"값은 동 기적으로 할당됩니다. 모든 "hi"그룹에는 최대 수의 "lo"항목이 제공되는데, 이는 동시 중복 항목에 대한 걱정없이 오프라인으로 할당 할 수 있습니다.

  1. "hi"토큰은 데이터베이스에 의해 할당되며 두 개의 동시 호출은 고유 한 연속 값을 볼 수 있습니다.
  2. "hi"토큰이 검색되면 "incrementSize"( "lo"항목 수) 만 필요합니다.
  3. 식별자 범위는 다음 공식으로 제공됩니다.

    [(hi -1) * incrementSize) + 1, (hi * incrementSize) + 1)

    "lo"값의 범위는 다음과 같습니다.

    [0, incrementSize)

    시작 값에서 적용되는 :

    [(hi -1) * incrementSize) + 1)
  4. 모든 "lo"값이 사용되면 새로운 "hi"값이 페치되고 사이클이 계속됩니다.

이 기사 에서 더 자세한 설명을 찾을 수 있습니다 .

그리고이 시각적 인 프리젠 테이션도 쉽게 수행 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

hi / lo 옵티마이 저는 식별자 생성을 최적화하는 데는 좋지만 식별자 전략에 대해 전혀 알지 못하면 데이터베이스에 행을 삽입하는 다른 시스템에서는 잘 작동하지 않습니다.

이벤트에게 최대 절전 모드 풀링-LO를 옵티 마이저를 제공하며, 하이 /로 제너레이터 전략의 장점을 제공하는 동시에이 시퀀스 할당 전략을 인식하지 못하는 다른 타사 클라이언트와의 상호 운용성을 제공합니다.

효율적이고 다른 시스템과 상호 운용이 가능하므로 풀 최적화 알고리즘은 레거시 hi / lo 식별자 전략보다 훨씬 더 나은 후보입니다.


나는 때때로 당신이 하하하를 이해하지 못한다. hi / lo 옵티마이 저는 식별자 생성을 최적화하는 데는 좋지만 (Ok good) 다른 시스템에서는 잘 작동하지 않습니다 (다른 시스템의 의미는 무엇입니까? ones?) 식별자 전략에 대해 전혀 알지 못하고 데이터베이스에 행을 삽입합니다.
Adelin

INSERT 문을 실행하려는 DBA와 같은 다른 시스템 그녀가 현재 시퀀스 데이터를 읽는다면이 특정 DB 테이블에서 힐로를 사용한다는 것을 알고 다음 식별자 값을 쉽게 알아낼 수 있다고 생각하십니까?
Vlad Mihalcea 2012

의견이 귀하의 답변에 적합하지 않은 경우 사과 드리지만 기본적으로 어떤 옵티마이 저가 사용되는지 궁금합니다. 아니면 DB에 의존합니까 (PostgreSQL을 사용하고 있습니까)? 현재 시퀀스 값과 생성 된 ID 사이의 관계를 알 수 없기 때문에. @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "name") @SequenceGenerator(name="name", sequenceName = "name_seq", allocationSize=100)ID를 사용 하고 있습니다.
Stefan Golubović가

1
Hibernate 5부터 Pooled는 Hi / lo가 아닌 새로운 Optimizer입니다. Pooled Optimizer에 대한 자세한 내용이 기사를 확인하십시오 .
Vlad Mihalcea

@ VladMihalcea, 나는 당신이 글 머리 기호 3에 오타가 있다고 생각합니다. 첫 발췌 문장은 , (hi * incrementSize) + 1)... , hi * incrementSize)맞습니까?
Huiagan

23

Lo는 캐시 된 할당 자로서, 키 공간을 사람이 현명하게 선택할 수있는 의미있는 크기의 범위 (예 : 한 번에 200 개의 키를 얻는 것)가 아닌 일부 기계 단어 크기에 따라 큰 청크로 나눕니다.

Hi-Lo 사용은 서버를 다시 시작할 때 많은 수의 키를 낭비하고 사람에게 친숙하지 않은 키 값을 생성하는 경향이 있습니다.

Hi-Lo 할당 기보다 "Linear Chunk"할당 기가 더 좋습니다. 이것은 비슷한 테이블 기반 원칙을 사용하지만 작고 편리한 크기의 청크를 할당하고 사람에게 친숙한 가치를 창출합니다.

create table KEY_ALLOC (
    SEQ varchar(32) not null,
    NEXT bigint not null,
    primary key (SEQ)
);

다음을 할당하려면 200 키 (서버에서 범위로 유지되고 필요에 따라 사용됨) :

select NEXT from KEY_ALLOC where SEQ=?;
update KEY_ALLOC set NEXT=(old value+200) where SEQ=? and NEXT=(old value);

이 트랜잭션을 커밋 할 수있는 경우 (다시 시도를 사용하여 경합 처리) 200 개의 키를 할당하고 필요에 따라 분배 할 수 있습니다.

청크 크기가 20에 불과한이 체계는 Oracle 시퀀스에서 할당하는 것보다 10 배 빠르며 모든 데이터베이스간에 100 % 이식 가능합니다. 할당 성능은 안녕과 같습니다.

Ambler의 아이디어와 달리 키 스페이스를 연속 선형 번호 선으로 취급합니다.

이렇게하면 복합 키에 대한 자극을 피할 수 있으며 (실제로는 좋은 아이디어는 아님) 서버를 다시 시작할 때 전체 단어를 낭비하지 않아도됩니다. "친숙한"인간 규모 키 값을 생성합니다.

Mr Ambler의 아이디어는 이와 비교하여 16 비트 또는 32 비트의 높은 비트를 할당하고 하이 워드가 증가함에 따라 큰 인간 친화적이지 않은 키 값을 생성합니다.

할당 된 키 비교 :

Linear_Chunk       Hi_Lo
100                65536
101                65537
102                65538
.. server restart
120                131072
121                131073
122                131073
.. server restart
140                196608

디자인 측면에서, 그의 솔루션은 Linear_Chunk보다 기본적으로 여러 줄 (복합 키, 대형 단어 제품)에서 더 복잡하지만 비교 이점은 없습니다.

Hi-Lo 디자인은 OO 매핑 및 지속성 초기에 일어났습니다. 요즘에는 최대 절전 모드와 같은 지속성 프레임 워크가 기본적으로 더 간단하고 더 나은 할당자를 제공합니다.


4
좋은 소식이지만 질문에 대답하지 않습니다.
orbfish

1
흥미로운 답변은 +1입니다. 본인은 대다수의 응용 프로그램이 간단한 접근 방식에 비해 Hi-Lo의 이점을 얻지 못한다는 데 동의합니다. 그러나 Hi-Lo는 동시 응용 프로그램에서 여러 할당 자의 특별한 경우에 더 적합하다고 생각합니다.
richj

1
감사합니다 @richj! 내 요점은 "선형 블록 할당"으로 여러 할당 자 또는 큰 블록 크기를 사용할 수 있지만 Hi / Lo와 달리 테이블의 키에 할당 자 NEXT_VAL 의 선형 대응 관계를 유지하고 조정 가능하다는 것입니다. HiLo와 달리 곱셈이 필요하지 않습니다. 단지 필요하지 않습니다! NEXT_HI의 곱셈 및 저장은 블록 크기를 변경하면 다음에 발행 될 키가 임의로 변경되므로 HiLo를 더 복잡하게하고 조정 성을 중단시킵니다. 참조 : literatejava.com/hibernate/…
Thomas W

2
여러 독립 할당 자에 관심이 있습니다. Hi-Lo를 사용하면 높은 값을 할당 자 ID / 블록 ID로 분할 할 수 있습니다. Linear Chunk에 동일한 접근 방식을 적용 할 수 있다는 것은 즉시 분명하지 않았지만 기본적으로 할당 자 사이의 총 범위를 나누는 것과 같은 문제입니다. 나는 지금 그것을 얻었다. 감사.
richj

1
아, 생각한 후에 SEQ 열이 테이블 이름에 매핑된다고 생각합니다. 예를 들어, 고객 테이블, 주문 테이블 용 할당 자 등이 있습니다. 용서하세요, 때로는 느립니다.
Rock Anthony Johnson

1

Hi / Lo 알고리즘이 내 경험에 기반한 복제 시나리오를 가진 여러 데이터베이스에 완벽하다는 것을 알았습니다. 이것을 상상해보십시오. 뉴욕 (별칭 01)에 서버가 있고 로스 앤젤레스 (별칭 02)에 다른 서버가있는 경우 PERSON 테이블이 있습니다 ... 그래서 사람이 생성 될 때 뉴욕에서는 항상 01을 HI 값으로 사용합니다 LO 값은 다음 보안입니다. 포 예제.

  • 010000010 제이슨
  • 010000011 데이비드
  • 010000012 테오

로스 앤젤레스에서는 항상 HI 02를 사용합니다. 예를 들면 다음과 같습니다.

  • 020000045 루퍼트
  • 020000046 오스왈드
  • 020000047 마리오

따라서 데이터베이스 복제 (어떤 브랜드에 상관없이)를 사용하면 기본 키와 충돌 등이 걱정되지 않고 모든 기본 키와 데이터가 쉽고 자연스럽게 결합됩니다.

이 시나리오에서 가장 좋은 방법입니다.


최대 절전 모드에서는 작동하지 않습니다. HiLo 알고리즘은 각 트랜잭션에서 새로운 시퀀스 값을 얻으므로 HI 카운터는 비례 적으로 증가합니다. 그러나 귀하의 예에서 HI 카운터는 하나의 DB에 대해 항상 일정합니다.
Dmitry1405
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.