문제

충돌을 확인하지 않고 짧고 고유 한 ID를 생성하고 싶습니다.

나는 현재 이와 같은 일을하고 있지만 현재 생성하는 ID는 무작위이며 루프에서 충돌을 확인하는 것은 성가 시며 레코드 수가 크게 증가하면 비용이 많이 듭니다.

일반적으로 충돌에 대해 걱정하는 것은 문제가되지 않지만, 내가 생성하고 싶은 고유 한 ID는 짧은 고유 한 문자열 5-8 문자, Alpha-numeric, Tinyurl과 마찬가지로.

편집 : 5 자로 시작하고 싶습니다. 6 천만 개의 항목을 치면 6으로 가십시오.

이를 위해, 나는 사용자로부터 숨겨져있는 auto_increment 값을 사용하고 대신에 제시 할 수 있다고 생각했다. MD5 또는 그로부터 고유 한 문자열을 생성하는 다른 방법.

생성 된 문자열은 선형으로 보이지 않아야하므로 Auto_incremented ID를 base 36 0-9A-Z]는 너무 단순하지만, 그와 같은 기능은 내가 이것과 함께가는 곳입니다.

편집 : 정보를 보호하는 데 사용되지 않으므로 보안은 문제가되지 않습니다. 단순히 더 긴 문자열의 바로 가기입니다. 고맙습니다.

귀하의 제안에 감사 드리며 지연에 대해 죄송합니다. 치과 의사..

도움이 되었습니까?

해결책

구조에 따라 올바른 것이 필요합니다. 즉 순열 기능 : 이것은 하나의 정수 (순차적 카운터)를 다른 정수 (순차적 카운터)에 대한 일대일, 가역적 매핑을 수행하는 함수입니다. 몇 가지 예 (이들의 조합이 모두 작동해야 함) :

  • 일부 비트 (xor를 사용하여 fi, ^ php)를 반전시킵니다.
  • 비트의 장소를 교환 (($ i & 0xc) >> 2 | ($ i & 0x3) << 2) 모든 비트의 순서를 뒤집습니다.
  • 상수 값 모듈로 추가 최대 범위 (위의 것과 결합하는 경우 2의 계수 여야합니다)

예 :이 함수는 0, 1, 2, 3, 5, .. .. 13, 4, 12, 7, 15, ..

$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;

편집하다

더 쉬운 방법은 형식의 공식으로 정의되는 선형 합동 발전기 (일반적으로 임의 숫자를 생성하는 데 사용되는 LCG)를 사용하는 방법입니다.

X_n+1 = (a * X_n + c) mod m

을 위한 좋은 가치 a, c 및 m의, x_0, x_1의 시퀀스는 0과 m-1 사이의 모든 숫자를 정확히 한 번 포함합니다. 이제 선형으로 증가하는 색인에서 시작하여 다음 "비밀"키로 LCG 시퀀스의 값.

edit2

구현 : 가능합니다 자신의 LCG 매개 변수를 설계하십시오, 그러나 당신이 잘못되면 전체 범위를 다루지 않으므로 (따라서 복제물이 있으므로) 여기에서 게시 된 매개 변수 세트를 사용하겠습니다. 이 종이:

a = 16807, c = 0, m = 2147483647

이것은 당신에게 2 ** 31의 범위를 제공합니다. pack ()를 사용하면 결과 정수를 문자열로 얻을 수 있습니다. base64_encode ()는 읽을 수있는 문자열 (최대 6 자, 바이트 당 6 비트)으로 만들 수 있으므로 기능이 될 수 있습니다.

substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)

다른 팁

현재 DateTime/Random Number의 MD5 해시를 생성하고 필요한 길이 (5-8 자)로 자르고 ID 필드로 저장할 수 있습니다.

이 정보를 데이터베이스에 저장하는 경우 충돌 확인을 위해 For Loop을 사용할 필요가 없지만 SELECT 문을 수행 할 수 있습니다.

SELECT count(1) c FROM Table WHERE id = :id

어디에 : ID는 새로 생성 된 ID입니다. C가 0보다 크면 이미 존재한다는 것을 알고 있습니다.

편집하다

이것은 가장 좋은 방법이 아닐 수도 있습니다. 그러나 나는 그것을 촬영할 것입니다. 그래서 당신이 필요로하는 것은 숫자를 독특한 짧은 문자열로 변환하는 것 같아서 순서 대비가 아닙니다.

당신이 말했듯이, Base64 인코딩은 이미 숫자를 짧은 문자열 변환으로 수행합니다. 시퀀스 문제를 피하기 위해 자동 생성 ID 사이에 일부 "랜덤"값 (고유 한 매핑)에 대한 매핑이있을 수 있습니다. 그런 다음 Base64 가이 고유 한 값을 인코딩 할 수 있습니다.

이 매핑을 다음과 같이 생성 할 수 있습니다. 임시 테이블 스토어 값은 1-10,000,000입니다. 임의 순서로 정렬하고지도 테이블에 저장하십시오.

INSERT INTO MappingTable (mappedId) SELECT values FROM TemporaryTable ORDER BY RAND()

MappingTable에 2 개의 필드 ID (자동으로 생성 된 ID가 이에 대해 조회 될 것임) 및 MappedId (Base64 인코딩을 생성하는 것)가있는 경우.

10,000,000에 가까워지면 위의 코드를 다시 실행하고 임시 테이블의 값을 10,000,001-20,000,000 이상으로 변경할 수 있습니다.

비트 XOR을 사용하여 일부 비트를 스크램블 할 수 있습니다.

select thefield ^ 377 from thetable;

+-----+---------+
| a   | a ^ 377 |
+-----+---------+
| 154 |     483 |
| 152 |     481 |
|  69 |     316 |
|  35 |     346 |
|  72 |     305 |
| 139 |     498 |
|  96 |     281 |
|  31 |     358 |
|  11 |     370 |
| 127 |     262 |
+-----+---------+

ID를 납치하기 위해 짧은 고유 문자열 뒤에 암호화 방법 만 찾아야하기 때문에 이것이 결코 안전하지 않을 것이라고 생각합니다. 루프에서 충돌을 확인하는 것이 실제로 당신의 설정에서 문제가 있습니까?

증분 숫자의 MD5는 괜찮을 것입니다. 그러나 MD5 (일반적으로 128 비트)까지 5-8 자까지 자르고 있다면 고유 한 서명 역할을하는 기능이 거의 손상 될 것입니다. ..

완전히 사실. 특히 80% 충돌 기회에 도달하면 잘린 MD5가 임의의 숫자만큼 좋을 것입니다.

그러나 어쨌든 데이터베이스를 사용하고 있기 때문에 고유 한 색인 만 사용하지 않겠습니까? 이런 식으로 MySQL 자체에 의해 Uniquness 점검이 (루프를 사용하는 것보다 훨씬 효율적인 방법으로) 수행됩니다. MD5 생성 키로 인서트를 시도하고 실패하면 다시 시도하십시오 ...

자동 증분 필드를 사용할 수없고 물론 고유 한 가치, 사용 uuid. 다른 것을 사용하기로 결정한 경우 (자동 증분 외에도) 충돌을 확인하지 않아도됩니다.

이 블로그 게시물에는 당신이 따르는 것에 가까운 것이 있습니다.

http://kevin.vanzonneveld.net/techblog/article/create_short_ids_with_php_like_youtube_or_tinyurl/

증분 숫자의 MD5는 괜찮을 것입니다. 그러나 MD5 (일반적으로 128 비트)까지 5-8 자까지 자르고 있다면 고유 한 서명 역할을하는 기능이 거의 손상 될 것입니다. ..

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top