Va chạm UUID [đóng]


33

Có ai đã thực hiện bất kỳ nghiên cứu thực tế nào về xác suất va chạm UUID, đặc biệt là với các UUID phiên bản 4 (ngẫu nhiên), cho rằng các trình tạo số ngẫu nhiên chúng tôi sử dụng không thực sự ngẫu nhiên và chúng tôi có thể có hàng chục hoặc hàng trăm máy giống hệt nhau chạy cùng một mã tạo UUID?

Các đồng nghiệp của tôi coi việc kiểm tra va chạm UUID là một sự lãng phí hoàn toàn thời gian, nhưng tôi luôn đặt mã để bắt một ngoại lệ khóa trùng lặp từ cơ sở dữ liệu và thử lại với UUID mới. Nhưng điều đó sẽ không giải quyết được vấn đề nếu UUID đến từ một quy trình khác và đề cập đến một đối tượng thực sự.


4
Câu hỏi đã được trả lời trên Stack Overflow: stackoverflow.com/questions/3038023/ , như hiển thị tìm kiếm cơ bản của Google: google.com/search?q=uuid+collision
Arseni Mourzenko

3
Câu hỏi đó là về các thuật toán cụ thể được sử dụng trong SQL * Server, khá chắc chắn KHÔNG phải là phiên bản 4 (ngẫu nhiên). Tôi đang hỏi về phiên bản 4 cụ thể.
Paul Tomblin

Bạn đang nói rằng việc triển khai NEWID()chức năng của SQL Server không phải là ngẫu nhiên? Nếu vậy, bạn có nguồn nào để sao lưu một yêu cầu như vậy không? Đầu ra của nó rõ ràng trông giống như v4 UUID đối với tôi. NEWSEQUENTIALID()được quyết định không hoàn toàn ngẫu nhiên, nhưng đó là mục đích của nó : để tạo ra các UUID hoạt động tốt (ít nhất là UUID có thể, ít nhất) như các khóa chỉ mục.
một CVn

1
Tôi đang đi theo câu trả lời cho câu hỏi được liên kết, trong đó tuyên bố rằng NEWID () chứa một số bit của địa chỉ mac, làm cho nó trở thành UUID V1 hoặc V2, không phải V4.
Paul Tomblin

2
Câu hỏi này dường như không có chủ đề vì đó là về một điều gì đó đã được thảo luận về quảng cáo trên internet, trong sách và đặc biệt là trên StackOverflow

Câu trả lời:


18

Wikipedia có một số chi tiết:

http://en.wikipedia.org/wiki/Universally_unique_identifier

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_d repeatates

Nhưng xác suất chỉ giữ nếu các bit là hoàn toàn ngẫu nhiên. Tuy nhiên, RFC http://tools.ietf.org/html/rfc4122#page-14 được liên kết trong câu trả lời khác xác định điều này cho phiên bản 4:

"4.4. [...] UUID phiên bản 4 có nghĩa là để tạo UUID từ các số thực ngẫu nhiên hoặc giả ngẫu nhiên. [...] Đặt tất cả các bit khác thành các giá trị được chọn ngẫu nhiên (hoặc giả ngẫu nhiên)."

Điều này khá nhiều cho phép mọi thứ từ trình tạo ngẫu nhiên xkcd http://xkcd.com/221/ đến một thiết bị phần cứng sử dụng nhiễu lượng tử. Các cân nhắc về bảo mật trong RFC:

"6. Các ứng dụng phân tán tạo UUID tại nhiều máy chủ phải sẵn sàng dựa vào nguồn số ngẫu nhiên ở tất cả các máy chủ. Nếu điều này không khả thi, nên sử dụng biến thể không gian tên."

Tôi đọc nó như là: Bạn đang ở một mình. Bạn chịu trách nhiệm cho trình tạo ngẫu nhiên của bạn trong ứng dụng của riêng bạn, nhưng điều này và bất cứ điều gì khác đều dựa trên niềm tin. Nếu bạn không tin tưởng vào khả năng của mình để hiểu chính xác và sử dụng trình tạo ngẫu nhiên mà bạn chọn, thì đó thực sự là một ý tưởng tốt để kiểm tra va chạm. Nếu bạn không tin tưởng lập trình viên của các quy trình khác, thì hãy kiểm tra va chạm hoặc sử dụng phiên bản UUID khác.


11

Bạn chắc chắn nên phát hiện nếu xảy ra xung đột và ứng dụng của bạn sẽ đưa ra một ngoại lệ nếu nó xảy ra. Ví dụ: nếu UUID được sử dụng làm khóa chính trong cơ sở dữ liệu, thì cơ sở dữ liệu sẽ gây ra lỗi khi chèn ID va chạm.

Tuy nhiên, tôi sẽ tin rằng viết mã để tạo UUID mới trong trường hợp va chạm và thử lại là một sự lãng phí thời gian. Cơ hội va chạm xảy ra là rất nhỏ đến nỗi ném ngoại lệ sẽ là một cách xử lý hoàn toàn hợp lý.

Hãy nhớ rằng, nó không chỉ lãng phí thời gian của bạn để viết mã, mà còn làm cho mã phức tạp hơn, khiến người tiếp theo khó đọc hơn, vì hầu như không đạt được gì cả.


2
UUID của bạn chỉ tốt như trình tạo ngẫu nhiên của bạn. Với một ( rất ) nghèo, một vụ va chạm sẽ không chỉ xảy ra mà là không thể tránh khỏi. Điều đó nói rằng có lẽ việc kiểm tra các bản sao ở thời điểm thế hệ thực sự sẽ là quá mức cần thiết, nhưng hy vọng rằng tình huống này có thể xảy ra và theo tôi, không quá nhiều để yêu cầu. Trong một số miền (ví dụ về chăm sóc sức khỏe) tôi nghĩ cần phải có mã để nắm bắt các tình huống như vậy (có lẽ là phát hiện va chạm trong cơ sở dữ liệu). bạn sẽ ngạc nhiên khi tôi dành bao nhiêu thời gian để gỡ lỗi những tình huống không bao giờ xảy ra.
Newtopian

1
Tôi nghĩ rằng tôi đã không làm cho mình rõ ràng. Tôi đã cập nhật câu trả lời để rõ ràng hơn.
Pete

7

Đây là một câu hỏi rất hay. Tôi không tin rằng nó đã được xem xét đầy đủ khi vội vàng sử dụng UUID ở mọi nơi. Tôi chưa tìm thấy nghiên cứu vững chắc nào.

Một gợi ý: bước đi rất cẩn thận ở đây, và biết rõ mật mã của bạn. Nếu bạn sử dụng UUID 128 bit, 'hiệu ứng sinh nhật' sẽ cho chúng tôi biết rằng có khả năng xảy ra xung đột sau khi bạn tạo khoảng 2 ^ 64 khóa, miễn là bạn có 128 bit entropy trong mỗi khóa .

Thực sự khá khó khăn để đảm bảo rằng đây là trường hợp. Tính ngẫu nhiên thực sự có thể được tạo ra từ (a) phân rã phóng xạ (b) nhiễu vô tuyến nền ngẫu nhiên, thường bị ô nhiễm trừ khi bạn cẩn thận (c) nhiễu điện tử được chọn phù hợp, ví dụ được lấy từ một diode Zener phân cực ngược. (Tôi đã chơi với bản cuối cùng và nó hoạt động như một bùa mê, BTW).

Tôi sẽ không tin vào các phát âm như "Tôi đã không thấy điều này trong một năm sử dụng", trừ khi người dùng đã tạo ra thứ gì đó tiếp cận các phím 2 ^ 64 (tức là khoảng 10 ^ 19) và kiểm tra tất cả chúng với nhau, a tập thể dục không tầm thường.

Vấn đề là thế này. Giả sử bạn chỉ có 100 bit entropy, khi so sánh các khóa của bạn với tất cả các khóa khác mà mọi người khác đang tạo trong một không gian khóa chung. Bạn sẽ bắt đầu thấy va chạm trong khoảng 2 ^ 50 tức là. khoảng 10 ^ 15 phím. Cơ hội của bạn để thấy một vụ va chạm nếu bạn đã điền vào cơ sở dữ liệu của mình chỉ với 1000 tỷ khóa vẫn không đáng kể. Và nếu bạn không kiểm tra, thì sau đó bạn sẽ nhận được các lỗi không mong muốn xuất hiện trong cơ sở dữ liệu có kích thước hàng peta của bạn. Điều này có thể cắn mạnh.

Thực tế là có nhiều cách tiếp cận để tạo ra các UUID như vậy sẽ gây ra sự lo lắng nhất thời. Khi bạn nhận ra rằng một vài máy phát điện sử dụng các quy trình 'thực sự ngẫu nhiên' với đủ entropy cho UUID loại 4, bạn nên quan tâm quá mức trừ khi bạn đã kiểm tra cẩn thận nội dung entropy của máy phát. (Hầu hết mọi người sẽ không làm điều này hoặc thậm chí biết cách; bạn có thể bắt đầu với bộ DieHarder). KHÔNG nhầm lẫn việc tạo số giả ngẫu nhiên với việc tạo số ngẫu nhiên thực sự.

Điều quan trọng là bạn nhận ra rằng entropy bạn đặt vào là entropy mà bạn có, và chỉ cần làm nhiễu khóa bằng cách áp dụng một chức năng mã hóa sẽ không làm thay đổi entropy. Có thể không rõ ràng bằng trực giác rằng nếu toàn bộ không gian của tôi bao gồm các chữ số 0 và 1, nội dung entropy giống như hai chuỗi sau, với điều kiện chúng là hai tùy chọn duy nhất: "Đây là một chuỗi thực sự phức tạp 293290729382832 * ! @@ # & ^% $) Vẫn chỉ có hai lựa chọn.

Sự ngẫu nhiên là khó khăn để có được đúng, và chỉ cần tin rằng "các chuyên gia đã xem xét nó, do đó nó ổn" có thể không đủ. Chuyên gia mật mã (và có một vài trong số những người thực sự thành thạo) là những người đầu tiên thừa nhận họ thường hiểu sai. Chúng tôi tin tưởng thật lòng, DigiNotar, v.v.

Tôi nghĩ Paul Tomblin đang thực hiện thận trọng thích hợp. 2c của tôi.


6

Vấn đề bạn gặp phải là nếu bạn sử dụng "Trình tạo số ngẫu nhiên" và bạn không biết trình tạo đó ngẫu nhiên như thế nào, thì xác suất va chạm thực sự là không xác định. Nếu các bộ tạo số ngẫu nhiên có tương quan theo một cách nào đó, xác suất va chạm có thể tăng đáng kể - có thể là nhiều, nhiều đơn đặt hàng hoặc cường độ.

Ngay cả khi bạn có xác suất va chạm rất nhỏ, bạn vẫn có một vấn đề cơ bản: Xác suất KHÔNG phải là 0. Điều này có nghĩa là một vụ va chạm SILL cuối cùng sẽ xảy ra, chúng sẽ không xảy ra rất thường xuyên.

Bạn càng tạo và sử dụng UUID càng thường xuyên thì khả năng xảy ra va chạm càng sớm. (tạo 1 năm một lần có nghĩa là thời gian chờ đợi lâu hơn so với tạo ra một triệu mỗi giây, tất cả những thứ khác đều bằng nhau).

Nếu xác suất đó là hữu hạn, không xác định và bạn sử dụng nhiều UUID thì bạn cần xem xét hậu quả của một vụ va chạm. Nếu không thể chấp nhận ném ngoại lệ và tắt ứng dụng kinh doanh, thì đừng làm điều đó! (Ví dụ ngoài đỉnh đầu của tôi: "Bạn có thể tắt máy chủ web giữa lúc cập nhật kiểm tra thư viện ... điều đó sẽ không xảy ra thường xuyên" và "Bạn có thể tắt hệ thống bảng lương ở giữa thực hiện trả lương ". Những quyết định này có thể là động thái hạn chế nghề nghiệp.)

Bạn có thể có một trường hợp tồi tệ hơn, một lần nữa tùy thuộc vào ứng dụng của bạn. Nếu bạn kiểm tra sự hiện diện của UUID (nghĩa là thực hiện tra cứu) và sau đó tạo một cái mới nếu chưa có - đó là một việc đủ phổ biến để làm - thì bạn có thể thấy bạn đang liên kết các bản ghi hoặc tạo mối quan hệ , trong thực tế, bạn đang kết nối 2 thứ thông qua UUID không nên kết nối. Đây là một cái gì đó khi ném một ngoại lệ sẽ không giải quyết được bất cứ điều gì và bạn có một mớ hỗn độn không thể phát hiện được tạo ra ở đâu đó. Đây là loại điều dẫn đến rò rỉ thông tin và có thể rất xấu hổ. (ví dụ: Đăng nhập vào ngân hàng của bạn và thấy bạn có thể thấy số dư của tài khoản của ai đó! Xấu!)

Tóm tắt: bạn cần xem xét cách sử dụng UUID của mình và hậu quả của một vụ va chạm. Điều này xác định xem bạn có nên cẩn thận để phát hiện và tránh va chạm, thực hiện một số hành động đơn giản trong trường hợp va chạm hoặc không làm gì. Một giải pháp đơn giản, duy nhất, phù hợp với tất cả có thể không phù hợp trong một số trường hợp.


2
"Xác suất (va chạm) KHÔNG phải là 0" Bất kỳ chuỗi có độ dài hữu hạn nào cũng có thuộc tính này. Ngay cả với UUID v4 hoàn toàn ngẫu nhiên, một khi bạn đã tạo 2 ^ 122 UUID duy nhất (128 bit trừ 4 bit phiên bản trừ 2 bit dành riêng), lần tiếp theo bạn tạo được đảm bảo là xung đột. Nhiều khả năng bạn sẽ va chạm sớm hơn thế. Câu hỏi lớn hơn là liệu một vụ va chạm sau khi lặp lại điều gì đó như lặp lại 5e36 có phải là một vấn đề hay không và điều đó không thể được trả lời chung (mặc dù rõ ràng có thể trả lời trong từng trường hợp cụ thể), như bạn nói trong phần tóm tắt.
một CVn

Tất nhiên. Đây là một tuyên bố rõ ràng (nhưng vẫn còn lặp lại). Vấn đề là có bao nhiêu mối tương quan với các bộ tạo số ngẫu nhiên. Điều này có thể làm tăng xác suất va chạm đáng kể (2 ^ lớn), nhưng bạn sẽ không biết bao nhiêu thứ trừ khi bạn thực hiện nhiều hoạt động đào, nghiên cứu hoặc tính toán. Giả sử xác suất va chạm tồi tệ hơn đáng kể so với giá trị tốt nhất có lẽ là thận trọng. Sau đó ... bạn cần phải xem xét hậu quả.
quick_now

0

Có hai vấn đề liên quan:

  1. Chất lượng của các bộ tạo số ngẫu nhiên được sử dụng.

  2. Số lượng UUID có thể được tạo ra.

Một UUID "ngẫu nhiên" có 122 bit ngẫu nhiên. Giả sử sự ngẫu nhiên hoàn hảo, bạn có thể mong đợi vụ va chạm đầu tiên vào khoảng 2 ^ 61 UUID được tạo (đó là căn bậc hai của 2 ^ 122). Nếu mọi người trên trái đất này tạo ra UUID mỗi giây, thì đó là 10.000.000.000 * 365 * 24 * 60 * 60 = 315360000000000000 UUID mỗi năm, khá gần với 2 ^ 58. Đó là, sau một vài năm bạn sẽ có được những va chạm đầu tiên. Trừ khi ứng dụng của bạn đến bất cứ nơi nào gần những con số đó, bạn có thể chắc chắn rằng bạn sẽ không bị va chạm nếu trình tạo ngẫu nhiên của bạn có chất lượng tốt.

Nói về trình tạo số ngẫu nhiên: Nếu bạn sử dụng các trình tạo thư viện C tiêu chuẩn (trực tiếp, gián tiếp hoặc các trình tạo tương tự), có thể gieo chúng theo thời gian, bạn sẽ bị bỏ qua. Chúng không thể vẽ đủ entropy để tránh va chạm. Tuy nhiên, nếu bạn đang ở trên linux, chỉ cần đọc 16 byte dữ liệu từ /dev/urandom: Điều này rút ra một nhóm entropy được khuấy bởi kernel, có quyền truy cập vào một số sự kiện ngẫu nhiên thực sự. Trừ khi bạn thường tạo UUID thực sự, thực sự sớm trong chuỗi khởi động, /dev/urandomnên hoạt động như một nguồn ngẫu nhiên thực sự.


-1

Tôi đã thử nghiệm nó một lần bằng cách sử dụng một chương trình (sức mạnh vũ phu) khá đơn giản, tạo ra 10 triệu UUID và tôi không gặp phải va chạm.

Các UUID RFC nói rằng UUID không chỉ là một bó (giả) số ngẫu nhiên.


1
Phiên bản 4, đây là phiên bản mà tôi đang hỏi, khá nhiều là một số các số ngẫu nhiên, ngoại trừ 6 bit sẽ giống hệt nhau trong tất cả chúng.
Paul Tomblin

8
10 triệu thậm chí không phải là một giọt trong xô. Chỉ có 1 trong 3E30 cơ hội va chạm. Nếu bạn tìm thấy một, tôi đã khuyên bạn nên nhanh chóng mua vé trong mọi cuộc xổ số bạn có thể!
Ross Patterson

@RossPatterson, điều tôi đặc biệt băn khoăn là liệu bạn có hàng trăm máy tính sử dụng thuật toán psuedo-Random chính xác trên cùng một phần cứng làm tăng đáng kể tỷ lệ va chạm. Tôi nghi ngờ nó sẽ.
Paul Tomblin

1
@Paul - Tôi chỉ nghĩ rằng nếu không có đủ entropy trong quy trình gieo hạt ban đầu - ví dụ: nếu hạt giống chỉ được tạo từ thời điểm trong ngày và tất cả các máy của bạn bắt đầu rất gần cùng một lúc. Tôi rất nghi ngờ rằng khả năng gieo hạt rất yếu - thậm chí có thể các số sê-ri phần cứng được sử dụng, tất nhiên sẽ là duy nhất cho mỗi máy.
Steve314

1
Than ôi, gieo hạt có thể rất yếu. Các hệ thống Linux rất thích gieo mầm PRNG từ các nguồn rất ngẫu nhiên (hoạt động của trình điều khiển thiết bị, v.v. ), nhưng trong các môi trường khác, tiêu chuẩn là sử dụng dấu thời gian hiện tại, với đủ máy móc đồng bộ hóa thời gian gần, có thể là một vấn đề.
Ross Patterson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.