2014-07-21 3 views
1

오늘 흥미로운 문제가 발생하여 해결책을 찾기 위해 인터넷을 검색했지만 아무 것도 찾지 못했습니다. 문제는 다음과 같습니다.무작위 1 대 1 해시 함수

사용자가 계정을 만들고 자신의 계정을 나타내는 고유 한 ID 번호 (예 : 123)가 부여됩니다. 다른 사용자가 계정을 만들 때 가장 최근에 생성 된 ID 번호에 1을 더하고이를 124에 할당 할 수 있습니다. 그러나 사용자 123이 그에게 등록되었다는 것을 이제 알았으므로 모든 사람을 완전히 익명화하지는 않습니다. 아주 작은 문제이지만 생각할 수있는 상황에 따라 더 큰 문제가 발생할 수 있습니다.

누가 더 먼저 왔는지 알 수 없도록 더 나은 해결책은 임의이지만 고유 한 ID를 갖는 것입니다.

이 문제를 해결하려면 표준 해시 함수 또는 난수 생성기를 사용하여 각 사람마다 고유 한 ID를 만들 수 있지만 충돌 가능성이 있습니다. 충돌을 확인하고 다시 실행하면이 문제를 피할 수 있지만이 예에서는 시스템의 속도가 느려질 것이라고 가정 해 봅시다. 또는 생성기가 불완전한 정보로 실행 중일 수 있으며 충돌이 있는지 확인할 수 없습니다.

내가 생각해 낸 다른 생각은 기본적으로 새로운 ID가 필요할 때 언제든지 상단에있는 카드를 쌓고 꺼내는 카드를 섞은 것입니다. 덱에서 카드가 떨어지면 마지막 덱의 가장 높은 카드에서 새 덱을 섞어서 섞습니다. 이 단점은 카드의이 데크를 보관해야하며 실수로 갑판을 잃어 버리면 다시 만들거나 계속하지 말고 많은 문제가 발생한다는 것입니다.

아주 비슷한 해결책은 매번 고정 시드를 기반으로이 셔플 데크를 다시 만들고 맨 위 대신 갑판의 n 번째 카드를 가져 오는 것입니다. 이 문제는 새로운 카드가 필요할 때마다이 덱을 섞는 데 많은 비용이 듭니다.

내가 생각해 보았던 다른 수학적 모델은 시퀀스의 다음 숫자가 예측 가능하다는 문제가 있습니다 (각 숫자는 이전 숫자와 고정 된 양입니다). 많은 사람들이 충돌을 겪는 문제가 있습니다.

내 질문은 : 거기에 "갑판"(읽기 : 배열) 메모리를 저장하거나 모든 함수 호출에서 다시 계산할 필요가없는 고유 ID를 얻으려면 숫자를 연결할 수있는 몇 가지 수학적 모델이 있습니까?

예를

randomID(number, seed, range) 
randomID(1,123,1000) = 284 
randomID(2,123,1000) = 739 
randomId(3,123,1000) = 088 
randomId(3,888,1000) = 912 

위해 나는 유망한 것으로 보인다 https://code.google.com/p/smhasher/wiki/MurmurHash3를 보았다,하지만 난 그것을 숫자의 임의의 범위에서 적용, 만 32 비트 또는 64bit를 통해 생각하지 않습니다.

+4

축하합니다! 당신은 방금 GUID를 생각해 냈습니다 : http://stackoverflow.com/questions/371762/what-exactly-is-guid-why-and-where-i-should-use-it – trailmax

+0

왜 trailmax의 대답이 코멘트인지 모르겠습니다. ,하지만 그것은 좋은 대답입니다. 대부분의 언어에는 GUID를 생성하는 라이브러리가 있습니다. 이 값은 고유 한 것이 아니라 충돌의 확률이 천문학적으로 작아서 모든 실제적인 목적으로 고유 한 순차적이지 않은 ID로 작동합니다. –

답변

1

지원해야 할 최대 사용자 수보다 큰 의사 난수 생성기를 선택할 수 있습니다. 그러면 다음을 생성하기 위해 마지막으로 사용한 값으로 PRNG를 시드하면됩니다. 어떻게 든 마지막으로 사용한 값을 추적하지 못하면 초기 시드를 사용하여 이미 등록 된 사용자 수를 기반으로 추가 값을 생성 할 수 있습니다. PRNG를 지나치게 큰 값으로 사용하지 않으려는 경우가 있습니다 (예 : 65536 명 미만인 경우 16 비트 1 2^16 기간을 찾을 수 있음). 따라서 숫자는 기억하기 쉽습니다. 여기

1

정확하게 저장하는 방법을 잘 모르지만 사이트를 사용할 모든 사용자를 처리 할 수있을만큼 큰 배열을 만들 수 있습니다. 그런 다음 임의의 n 번째 인덱스에서 시작하여 임의의 시간을 반복하는 임의의 숫자를 만들 수 있습니다. 비어있는 색인에 해당 할 때 색인에 값 (예 : 1 또는 무엇이든)을 넣으면 사용자는 색인의 ID를 얻습니다. 해당 인덱스에 이미 값이 있으면 난수가 인덱스에 올 때까지 프로세스를 반복하십시오. 이것에 대한 좋은 점은 난수를 현재 색인에 추가 할 수 있기 때문에 반복하지 않아도된다는 것입니다. 유일한 논리는 배열의 끝에 도달하는 경우를 처리하는 일종의 mod 함수입니다. 희망이 도움이됩니다.

+0

이것은 내가 카드 더미를 의미하는 것이고, 나는 단지 비유를 사용하고 있었다. 내 게시물에 명확히하겠습니다 :) –

1

유연하고 효율적인 방법입니다 : -

  1. 은 해시 테이블을 유지한다.
  2. 사용하려는 해시 테이블 크기에 비례하는 숫자 M을 선택하십시오.
  3. 첫 번째 Mids에 대해 M 개의 난수를 생성하고 해시 테이블 조회로 충돌을 방지합니다.
  4. M 세대가 끝날 때 크기 M + 1의 배열로 사용되지 않으면 M 개의 이전 ID의 모든 id + 1 값을 더합니다.
  5. 더 일찍 사용하지 않으면 id 0을 추가하십시오.
  6. 다음 id 생성마다 임의로 배열에서 id를 선택하십시오.
  7. 해시 테이블에없는 경우 id + 1을 추가하십시오.

장점 : -

  1. 당신은 더 무작위로 당신의 식별자가있는 M M. 이상을 사용 사용 임의성 및 저장을 조절 할 수 있습니다. 사용 된 공간과 임의성 사이에 상충 관계가있을 수 있습니다.
  2. 당신은 해시 테이블과 배열에 redis와 같은 메모리 내장 데이터베이스를 쉽게 사용할 수 있습니다. 고유 ID의 생성을위한
  3. 시간 복잡도는 (1)
1

이 작업을 성취하기 위해 사용할 수 block cipher O이다. 블록 (고정 된 비트 수)을 암호화하면 암호 키는 동일한 비트 수의 다른 블록에이를 매핑합니다. 암호 해독 단계는이를 취소합니다. 두 개의 서로 다른 블록이 동일한 블록에 매핑되지 않습니다.

사용자 ID를 64 비트라고 가정하고 64 비트 블록 암호와 비밀 키로 암호화하면 사용자 ID가 임의로 지정됩니다. 원래 사용자 ID를 다시 얻으려면 동일한 키로 해독하십시오.

Blowfish 또는 AES과 같은 잘 알려진 알고리즘을 사용하는 경우 결과는 암호화 된 방식으로 얻을 수 있습니다.