JavaScript에서 UUID를 생성 할 때 충돌이 발생합니까?
이것은 이 질문 과 관련 이 있습니다. 이 답변의 아래 코드를 사용하여 JavaScript에서 UUID를 생성합니다.
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
이 솔루션은 잘 작동하는 것처럼 보였지만 충돌이 발생합니다. 내가 가진 것은 다음과 같습니다.
- Google 크롬에서 실행되는 웹 앱.
- 16 명의 사용자.
- 이러한 사용자에 의해 지난 2 개월 동안 약 4000 개의 UUID가 생성되었습니다.
- 약 20 건의 충돌이 발생했습니다. 예를 들어 오늘 생성 된 새 UUID가 약 2 개월 전과 동일했습니다 (다른 사용자).
이 문제의 원인은 무엇이며 어떻게 방지 할 수 있습니까?
내 추측으로는 Math.random()
어떤 이유로 시스템에서 고장났다 는 것 입니다 (그렇게 들리 겠지만 기이함). 이것은 내가 본 사람이 충돌을 겪는 첫 번째 보고서입니다.
node-uuid
해당 코드에서 16 진수 분포를 테스트하는 데 사용할 수 있는 테스트 도구 가 있습니다. 괜찮아 보이면 그렇지 않은 Math.random()
것이므로 사용중인 UUID 구현을 uuid()
메서드 로 대체하고 여전히 좋은 결과를 얻는 지 확인하십시오.
[업데이트 : 방금 시작할 때 버그에 대한 Veselin의 보고서를 보았습니다 Math.random()
. 문제는 시작시에만 발생하므로 node-uuid
테스트가 유용하지 않을 수 있습니다. devoluk.com 링크에서 더 자세히 설명하겠습니다.]
실제로 충돌이 있지만 Google 크롬에서만 발생합니다. 여기에서 주제에 대한 내 경험을 확인하십시오.
http://devoluk.com/google-chrome-math-random-issue.html
(링크는 2019 년 기준으로 끊어졌습니다 . 아카이브 링크 : https://web.archive.org/web/20190121220947/http://devoluk.com/google-chrome-math-random-issue.html .)
충돌은 Math.random의 처음 몇 번의 호출에서만 발생하는 것 같습니다. 위의 createGUID / testGUIDs 메서드를 실행하면 (분명히 내가 시도한 첫 번째) 충돌이 전혀 발생하지 않습니다.
따라서 전체 테스트를 수행하려면 Chrome을 다시 시작하고, 32 바이트를 생성하고, Chrome을 다시 시작하고, 생성하고, 다시 시작하고, 생성해야합니다.
다른 사람들이이 사실을 알 수 있도록 여기에 언급 된 UUID 생성 기법을 사용하여 놀랍도록 많은 수의 명백한 충돌이 발생했습니다. 이러한 충돌은 난수 생성기 에서 seedrandom 으로 전환 한 후에도 계속되었습니다 . 당신이 상상할 수 있듯이 그로 인해 머리카락이 찢어졌습니다.
나는 결국 문제가 Google의 웹 크롤러 봇과 관련된 (거의?) 독점적이라는 것을 알게되었습니다. user-agent 필드에서 "googlebot"을 사용하여 요청을 무시하기 시작하자 충돌이 사라졌습니다. 나는 그들이 JS 스크립트의 결과를 반 지능적인 방식으로 캐시해야한다고 생각하는데, 최종 결과는 그들의 스파이더 링 브라우저가 일반 브라우저가하는 방식으로 작동한다고 믿을 수 없다는 것입니다.
그냥 참고로.
나는 이것을 귀하의 질문에 대한 의견으로 게시하고 싶었지만 분명히 StackOverflow가 나를 허용하지 않을 것입니다.
방금 게시 한 UUID 알고리즘을 사용하여 Chrome에서 100,000 번의 반복 테스트를 실행했지만 충돌이 발생하지 않았습니다. 다음은 코드 스 니펫입니다.
var createGUID = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
var testGUIDs = function(upperlimit) {
alert('Doing collision test on ' + upperlimit + ' GUID creations.');
var i=0, guids=[];
while (i++<upperlimit) {
var guid=createGUID();
if (guids.indexOf(guid)!=-1) {
alert('Collision with ' + guid + ' after ' + i + ' iterations');
}
guids.push(guid);
}
alert(guids.length + ' iterations completed.');
}
testGUIDs(100000);
여기서 다른 일이없는 게 확실합니까?
이 UUID 솔루션을 처음 게시 한 답변 은 2017-06-28에 업데이트되었습니다.
Chrome, Firefox 및 Safari의 Math.random PRNG 품질 상태에 대해 설명하는 Chrome 개발자 의 좋은 기사입니다 . tl; dr-2015 년 말 현재 "아주 훌륭"하지만 암호화 품질은 아닙니다. 이 문제를 해결하기 위해 ES6,
crypto
API 및 약간의 JS 마법사 를 사용하는 위 솔루션의 업데이트 된 버전이 있습니다 .
function uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
)
}
console.log(uuidv4());
The answers here deal with "what's causing the issue?" (Chrome Math.random seed issue) but not "how can I avoid it?".
If you are still looking for how to avoid this issue, I wrote this answer a while back as a modified take on Broofa's function to get around this exact problem. It works by offsetting the first 13 hex numbers by a hex portion of the timestamp, meaning that even if Math.random is on the same seed it will still generate a different UUID unless generated at the exact same millisecond.
참고URL : https://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript
'program story' 카테고리의 다른 글
일하는 사람을위한 결합 자 설명 (0) | 2020.09.06 |
---|---|
'할당 분기 조건 크기가 너무 큼'은 무엇을 의미하며 어떻게 해결합니까? (0) | 2020.09.06 |
교리 수화 란 무엇입니까? (0) | 2020.09.06 |
T-SQL : UPDATE 문에서 CASE를 사용하여 조건에 따라 특정 열 업데이트 (0) | 2020.09.05 |
C int 배열을 0으로 재설정 : 가장 빠른 방법? (0) | 2020.09.05 |