การชนของ UUID [ปิด]


33

มีใครทำวิจัยจริงเกี่ยวกับความน่าจะเป็นของการชนของ UUID โดยเฉพาะกับ UUIDs รุ่นที่ 4 (สุ่ม) เนื่องจากเครื่องกำเนิดหมายเลขสุ่มที่เราใช้นั้นไม่ได้สุ่มอย่างแท้จริงและเราอาจมีเครื่องที่เหมือนกันหลายสิบหรือหลายร้อยเครื่องทำงานด้วยรหัสเดียวกัน สร้าง UUIDs หรือไม่

เพื่อนร่วมงานของฉันพิจารณาการทดสอบว่าการชนกันของ UUID นั้นเป็นการเสียเวลาอย่างสมบูรณ์ แต่ฉันมักจะใส่รหัสเพื่อตรวจสอบข้อยกเว้นคีย์ซ้ำจากฐานข้อมูลและลองใหม่ด้วย UUID ใหม่ แต่นั่นจะไม่แก้ปัญหาถ้า UUID มาจากกระบวนการอื่นและอ้างถึงวัตถุจริง


4
คำถามได้ถูกตอบแล้วใน Stack Overflow: stackoverflow.com/questions/3038023/ …ดังที่แสดงการค้นหาพื้นฐานของ Google: google.com/search?q=uuid+collision
Arseni Mourzenko

3
คำถามนั้นเกี่ยวกับอัลกอริทึมเฉพาะที่ใช้ใน SQL * Server ซึ่งค่อนข้างแน่นอนไม่ใช่รุ่น 4 (สุ่ม) ฉันกำลังถามเกี่ยวกับรุ่น 4 โดยเฉพาะ
พอลทอมบลิ

คุณกำลังบอกว่าการใช้งานNEWID()ฟังก์ชั่นของ SQL Server นั้นไม่สุ่ม ถ้าเป็นเช่นนั้นคุณมีแหล่งข้อมูลใดบ้างเพื่อสำรองข้อเรียกร้องดังกล่าวหรือไม่? ผลลัพธ์ของมันดูเหมือน v4 UUIDs สำหรับฉันอย่างชัดเจน NEWSEQUENTIALID()จะไม่สุ่มอย่างสมบูรณ์ แต่เป็นจุดประสงค์ : เพื่อสร้าง UUID ซึ่งทำงานได้ดี (รวมทั้ง UUID สามารถเป็นอย่างน้อย) เป็นคีย์ดัชนี
CVn

1
ฉันจะตอบคำถามที่เชื่อมโยงซึ่งระบุว่า NEWID () ประกอบด้วยบิตของที่อยู่ mac ซึ่งทำให้เป็น V1 หรือ V2 UUID ไม่ใช่ V4
พอลทอมบลิ

2
คำถามนี้ดูเหมือนจะไม่เป็นหัวข้อเพราะเป็นเรื่องเกี่ยวกับ ad-nauseum ที่กล่าวถึงบนอินเทอร์เน็ตในหนังสือและโดยเฉพาะอย่างยิ่งใน StackOverflow

คำตอบ:


18

Wikipedia มีรายละเอียดบางอย่าง:

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

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

แต่ความน่าจะเป็นนั้นก็ต่อเมื่อบิตนั้นสุ่มอย่างสมบูรณ์ อย่างไรก็ตาม RFC http://tools.ietf.org/html/rfc4122#page-14เชื่อมโยงในคำตอบอื่น ๆ จะกำหนดสิ่งนี้สำหรับรุ่น 4:

"4.4. [... ] เวอร์ชั่น 4 UUID มีความหมายสำหรับการสร้าง UUID จากตัวเลขสุ่มแบบสุ่มหรือแบบหลอกเทียม [... ] ตั้งค่าบิตอื่น ๆ ทั้งหมดให้เป็นค่าที่เลือกแบบสุ่ม (หรือหลอกแบบสุ่ม)"

นี้สวยมากช่วยให้อะไรจากเครื่องกำเนิดสุ่ม xkcd http://xkcd.com/221/ไปยังอุปกรณ์ฮาร์ดแวร์ที่ใช้เสียงควอนตัม ข้อควรพิจารณาด้านความปลอดภัยใน RFC:

"6. แอปพลิเคชันแบบกระจายที่สร้าง UUIDs ที่โฮสต์หลายแห่งจะต้องเต็มใจที่จะพึ่งพาแหล่งที่มาของตัวเลขสุ่มที่โฮสต์ทั้งหมดหากไม่สามารถทำได้ควรใช้ตัวแปรเนมสเปซ"

ฉันอ่านสิ่งนี้เป็น: คุณอยู่คนเดียว คุณต้องรับผิดชอบต่อเครื่องกำเนิดไฟฟ้าแบบสุ่มภายในแอปพลิเคชันของคุณเอง แต่สิ่งนี้และสิ่งอื่นนั้นขึ้นอยู่กับความไว้วางใจ หากคุณไม่ไว้วางใจความสามารถของคุณเองในการทำความเข้าใจและใช้ตัวสร้างแบบสุ่มที่คุณเลือกอย่างถูกต้องมันเป็นความคิดที่ดีที่จะตรวจสอบการชน หากคุณไม่เชื่อถือโปรแกรมเมอร์ของกระบวนการอื่น ๆ ให้ตรวจสอบการชนกันหรือใช้ UUID เวอร์ชันอื่น


11

คุณควรตรวจสอบว่ามีการชนกันหรือไม่และแอปพลิเคชันของคุณควรมีข้อยกเว้นหากเกิดขึ้น เช่นถ้าใช้ UUID เป็นคีย์หลักในฐานข้อมูลดังนั้นฐานข้อมูลควรจะเกิดข้อผิดพลาดเมื่อใส่ ID การชนกัน

อย่างไรก็ตามฉันเชื่อว่าการเขียนรหัสเพื่อสร้าง UUID ใหม่ในกรณีที่มีการชนกันและพยายามอีกครั้งเพื่อเสียเวลา โอกาสของการปะทะที่เกิดขึ้นมีน้อยมากซึ่งการโยนข้อยกเว้นจะเป็นวิธีที่เหมาะสมที่สุดในการจัดการกับมัน

โปรดจำไว้ว่าไม่เพียงเป็นการเสียเวลาเขียนรหัส แต่ยังทำให้รหัสซับซ้อนขึ้นทำให้ผู้อ่านคนถัดไปอ่านยากขึ้นเพราะแทบจะไม่ได้รับประโยชน์เลย


2
UUID ของคุณดีพอ ๆ กับตัวสร้างแบบสุ่ม ด้วยมาก ( มาก ) คนยากจนชนไม่เพียง แต่จะเกิดขึ้นอย่างหลีกเลี่ยงไม่ ที่กล่าวว่าอาจจะตรวจสอบซ้ำในเวลารุ่นแน่นอนจะ overkill แต่คาดหวังว่าสถานการณ์อาจเกิดขึ้นและในความคิดของฉันไม่มากที่จะขอ ในบางโดเมน (ตัวอย่างด้านการดูแลสุขภาพ) ฉันคิดว่าจำเป็นต้องมีรหัสที่ตรวจจับสถานการณ์เช่นนั้น (อาจเป็นการตรวจจับการชนกันของข้อมูลในฐานข้อมูล) คุณจะประหลาดใจว่าฉันใช้เวลาในการแก้ไขจุดบกพร่องมากน้อยเพียงใด
Newtopian

1
ฉันคิดว่าฉันไม่ได้ทำให้ชัดเจน ฉันได้ปรับปรุงคำตอบให้ชัดเจนยิ่งขึ้น
Pete

7

นี่เป็นคำถามที่ดีมาก ฉันไม่เชื่อว่ามันได้รับการพิจารณาอย่างเพียงพอในการเร่งใช้ UUID ทุกที่ ฉันไม่พบงานวิจัยที่แข็งแกร่ง

คำแนะนำ: เดินอย่างระมัดระวังที่นี่และรู้จักการเข้ารหัสของคุณดี หากคุณใช้ 128 บิต UUID 'ที่มีผลบังคับใช้วันเกิด' บอกเราว่าการปะทะกันมีแนวโน้มหลังจากที่คุณได้สร้างขึ้นประมาณ 2 ^ 64 คีย์ให้คุณมี 128 บิตเอนโทรปีในแต่ละคีย์

เป็นจริงค่อนข้างยากที่จะตรวจสอบให้แน่ใจว่าเป็นกรณีนี้ การสุ่มอย่างแท้จริงสามารถเกิดขึ้นได้จาก (ก) การสลายตัวของกัมมันตภาพรังสี (b) เสียงรบกวนจากพื้นหลังแบบสุ่มซึ่งมักจะมีการปนเปื้อนเว้นแต่คุณจะระมัดระวัง (c) เลือกเสียงอิเล็กทรอนิกส์ที่เหมาะสมเช่นนำมาจากไดโอดซีเนอร์แบบย้อนกลับ (ฉันเล่นกับเกมสุดท้ายแล้วมันก็ใช้งานได้เหมือน BTW)

ฉันจะไม่เชื่อถือการออกเสียงเช่น "ฉันไม่ได้เห็นสิ่งนี้ในหนึ่งปีของการใช้งาน" ยกเว้นว่าผู้ใช้สร้างบางสิ่งบางอย่างที่กำลังจะมาถึงคีย์ 2 ^ 64 (เช่นประมาณ 10 ^ 19) และตรวจสอบพวกเขาทั้งหมดกับ a การออกกำลังกายที่ไม่น่ารำคาญ

ปัญหาคือสิ่งนี้ สมมติว่าคุณมีเอนโทรปี 100 บิตเมื่อเปรียบเทียบคีย์ของคุณกับคีย์อื่น ๆ ที่ทุกคนกำลังสร้างในพื้นที่คีย์ทั่วไป คุณจะเริ่มเห็นการชนกันในประมาณ 2 ^ 50 เช่น ประมาณ 10 ^ 15 ปุ่ม โอกาสที่คุณจะพบการชนถ้าคุณเติมฐานข้อมูลของคุณด้วยปุ่มเพียง 1,000 ล้านปุ่มก็ยังไม่สำคัญ และถ้าคุณไม่ตรวจสอบคุณจะได้รับข้อผิดพลาดที่ไม่คาดคิดที่คืบคลานเข้าไปในฐานข้อมูลขนาดแถวของคุณ นี่อาจกัดยาก

ความจริงที่ว่ามีหลายวิธีในการสร้าง UUID ดังกล่าวควรทำให้เกิดอาการกระตุกชั่วขณะของความกังวล เมื่อคุณรู้ว่ามีผู้สร้างไม่กี่รายที่ใช้กระบวนการ 'สุ่มอย่างแท้จริง' ด้วยเอนโทรปีที่เพียงพอสำหรับ UUID ประเภท 4 คุณควรกังวลมากเกินไปจนกว่าคุณจะตรวจสอบเนื้อหาของเอนโทรปีอย่างระมัดระวัง (คนส่วนใหญ่จะไม่ทำสิ่งนี้หรือรู้วิธีคุณอาจเริ่มด้วยชุด DieHarder) อย่าสับสนการสร้างหมายเลขเทียมโดยใช้การสร้างตัวเลขสุ่มจริง

มันสำคัญมากที่คุณจะต้องตระหนักว่าเอนโทรปีที่คุณใส่เข้าไปนั้นเป็นเอนโทรปีที่คุณมีอยู่ อาจไม่ชัดเจนว่าถ้าพื้นที่ทั้งหมดของฉันประกอบด้วยตัวเลข 0 และ 1 เนื้อหาของเอนโทรปีจะเหมือนกับของสองสายต่อไปนี้หากพวกมันเป็นเพียงสองตัวเลือก: "นี่เป็นสตริงที่ซับซ้อนจริงๆ 293290729382832 * ! @@ # & ^% $$),. m} "และ" และตอนนี้สำหรับบางสิ่งบางอย่างโดยสิ้นเชิง " ยังคงมีเพียงสองตัวเลือก

การสุ่มเป็นเรื่องยากที่จะทำให้ถูกต้องและเพียงแค่เชื่อว่า "ผู้เชี่ยวชาญได้ตรวจสอบแล้วมันก็โอเค" อาจไม่พอเพียง ผู้เชี่ยวชาญ cryptographers (และมีไม่กี่คนที่มีความเชี่ยวชาญจริง ๆ ) เป็นคนแรกที่ยอมรับว่าพวกเขามักจะทำผิด เราเชื่อมั่นในหัวใจที่แตกต่าง DigiNotar ฯลฯ

ฉันคิดว่า Paul Tomblin ใช้ความระมัดระวังอย่างเหมาะสม 2c ของฉัน


6

ปัญหาที่คุณมีคือถ้าคุณใช้ "ตัวสร้างตัวเลขสุ่ม" และคุณไม่รู้ว่าตัวกำเนิดนั้นเป็นแบบสุ่มอย่างไรความน่าจะเป็นที่จะเกิดการชนนั้นไม่เป็นที่ทราบแน่ชัด หากเครื่องกำเนิดจำนวนสุ่มมีความสัมพันธ์กันในทางใดทางหนึ่งความน่าจะเป็นของการชนอาจเพิ่มขึ้นอย่างมาก - อาจมีหลายคำสั่งหรือขนาด

แม้ว่าคุณจะมีโอกาสเกิดการชนน้อยมาก แต่คุณมีปัญหาพื้นฐาน: ความน่าจะเป็นไม่ใช่ 0 ซึ่งหมายความว่าการชนจะเกิดขึ้นในที่สุดพวกเขาก็จะไม่เกิดขึ้นบ่อยนัก

ยิ่งคุณสร้างและใช้ UUID บ่อยครั้งเท่าใดการชนก็จะเกิดขึ้นเร็วขึ้น (การสร้าง 1 ปีหมายถึงเวลาที่รอคอยนานกว่าการสร้างล้านต่อวินาทีสิ่งอื่น ๆ จะเท่ากัน)

หากความน่าจะเป็นนั้นไม่ทราบแน่ชัดและคุณใช้ UUID จำนวนมากคุณต้องพิจารณาผลที่ตามมาของการชน หากไม่สามารถยอมรับข้อยกเว้นและปิดแอปพลิเคชันธุรกิจได้โปรดอย่าทำเช่นนั้น! (ตัวอย่างปิดส่วนบนของหัวของฉัน: "ก็โอเคที่จะปิดเว็บเซิร์ฟเวอร์ในช่วงกลางของการปรับปรุงการตรวจสอบห้องสมุด ... มันจะไม่เกิดขึ้นบ่อย" และ "มันก็โอเคที่จะปิดระบบบัญชีเงินเดือนในช่วงกลางของ การดำเนินการจ่ายเงิน "การตัดสินใจเหล่านี้อาจ จำกัด การย้ายอาชีพ)

คุณอาจมีคดีที่แย่กว่านั้นขึ้นอยู่กับใบสมัครของคุณอีกครั้ง หากคุณทดสอบการมี UUID (เช่นทำการค้นหา) จากนั้นสร้างใหม่หากไม่มีอยู่แล้ว - ซึ่งเป็นสิ่งที่ทำกันมากพอ - จากนั้นคุณอาจพบว่าคุณกำลังเชื่อมโยงบันทึกหรือสร้างความสัมพันธ์ ในความเป็นจริงเมื่อคุณกำลังเชื่อมต่อ 2 สิ่งผ่าน UUID ที่ไม่ควรติด นี่คือสิ่งที่การโยนข้อยกเว้นจะไม่สามารถแก้ไขอะไรได้และคุณมีระเบียบที่ไม่สามารถตรวจจับได้ที่อื่น นี่คือสิ่งที่นำไปสู่การรั่วไหลของข้อมูลและอาจเป็นเรื่องที่น่าอายมาก (เช่นเข้าสู่ระบบธนาคารของคุณและพบว่าคุณสามารถเห็นยอดเงินคงเหลือในบัญชีคนอื่น! แย่!)

สรุป: คุณต้องพิจารณาวิธีการใช้ UUID ของคุณและผลที่ตามมาของการชน สิ่งนี้จะกำหนดว่าคุณควรตรวจจับและหลีกเลี่ยงการชนดำเนินการอย่างง่าย ๆ ในกรณีที่เกิดการชนหรือไม่ทำอะไรเลย วิธีแก้ปัญหาที่เรียบง่ายและเป็นหนึ่งเดียวเหมาะกับทุกคนมีแนวโน้มที่จะไม่เหมาะสมในบางสถานการณ์


2
"ความน่าจะเป็น (ของการชนกัน) ไม่ใช่ 0"ลำดับความยาวแน่นอนมีคุณสมบัตินี้ แม้จะใช้v4 UUID แบบสุ่มสมบูรณ์แบบเมื่อคุณสร้าง UUID ที่ไม่ซ้ำกัน 2 ^ 122 (128 บิตลบด้วยบิตรุ่น 4 บิตลบด้วย 2 สงวนบิต) ชิ้นถัดไปที่คุณสร้างจะรับประกันว่าจะเป็นการชนกัน เป็นไปได้ว่าคุณจะชนกันเร็วกว่านั้น คำถามที่ใหญ่กว่าคือการชนกันของข้อมูลซ้ำ ๆ เช่น 5e36 ซ้ำแล้วซ้ำอีกหรือไม่และไม่สามารถตอบได้โดยทั่วไป (แม้ว่าจะเป็นไปได้ที่จะตอบในแต่ละกรณี) เช่นเดียวกับที่คุณพูดในบทสรุป
CVN

แน่นอน. นี่เป็นคำแถลงที่ชัดเจน (แต่ยังคงมีการพูดซ้ำ) ปัญหาคือเท่าใดความสัมพันธ์กับเครื่องกำเนิดตัวเลขสุ่มมี นี้อาจเพิ่มความน่าจะเป็นของการปะทะกันอย่างมีนัยสำคัญ (ขนาดใหญ่ 2 ^) แต่วิธีการมากเป็นสิ่งที่คุณจะไม่ทราบจนกว่าคุณจะทำมากของการขุดการวิจัยหรือการคำนวณ สมมติว่าความน่าจะเป็นของการชนนั้นแย่กว่าค่าที่ดีที่สุดอย่างระมัดระวัง หลังจากนั้น ... คุณต้องพิจารณาผลที่ตามมา
quick_now

0

มีสองประเด็นที่เกี่ยวข้อง:

  1. คุณภาพของเครื่องกำเนิดตัวเลขสุ่มที่ใช้

  2. จำนวน UUID ที่อาจถูกสร้างขึ้น

UUID ที่ "สุ่ม" มี 122 บิตสุ่ม สมมติว่าการสุ่มสมบูรณ์แบบคุณสามารถคาดหวังว่าการปะทะครั้งแรกที่ประมาณ 2 ^ 61 สร้าง UUIDs (นั่นคือรากที่สองของ 2 ^ 122) หากทุกคนบนโลกนี้ต้องสร้าง UUID ต่อวินาทีนั่นคือ 10,000,000,000 * 365 * 24 * 60 * 60 = 315360000000000000 UUIDs ต่อปีซึ่งค่อนข้างใกล้กับ 2 ^ 58 นั่นคือหลังจากไม่กี่ปีคุณจะได้รับการชนครั้งแรก หากแอปพลิเคชันของคุณเข้าใกล้ตัวเลขเหล่านี้คุณก็มั่นใจได้เลยว่าคุณจะไม่ได้รับความขัดแย้งหากตัวสร้างแบบสุ่มของคุณมีคุณภาพดี

การพูดคุยเกี่ยวกับเครื่องกำเนิดเลขสุ่ม: หากคุณใช้เครื่องกำเนิดไฟฟ้าไลบรารีมาตรฐาน C (ทั้งทางตรงหรือทางอ้อมเครื่องกำเนิดไฟฟ้าที่คล้ายกัน) อาจจะทำการเพาะเวลาด้วยคุณจะถูก skrewed สิ่งเหล่านี้ไม่สามารถดึงเอนโทรปีเพียงพอเพื่อหลีกเลี่ยงการชน อย่างไรก็ตามถ้าคุณอยู่บน linux ให้อ่านข้อมูลจาก 16 ไบต์/dev/urandom: สิ่งนี้ดึงเอนโทรปีของพูลที่กวนโดยเคอร์เนลซึ่งสามารถเข้าถึงเหตุการณ์สุ่มจริง ๆ เว้นแต่ว่าคุณจะสร้าง UUID จริงๆแล้ว แต่เนิ่นๆในลำดับการบู๊ต/dev/urandomควรทำตัวเหมือนแหล่งสุ่มที่แท้จริง


-1

ฉันได้ทำการทดสอบครั้งเดียวโดยใช้โปรแกรมที่ค่อนข้างเรียบง่าย (แรงเดรัจฉาน) ที่สร้าง UUID-10 ล้านตัวและฉันไม่เคยเจอการชน

UUID RFCบอกว่า UUID ไม่ได้เป็นเพียงพวงของ (หลอก) ตัวเลขสุ่ม


1
เวอร์ชัน 4 ซึ่งเป็นสิ่งที่ฉันถามเกี่ยวกับตัวเลขสุ่มเป็นจำนวนมากยกเว้น 6 บิตซึ่งจะเหมือนกันทุกประการ
พอลทอมบลิ

8
10 ล้านคนไม่แม้แต่ตกอยู่ในถัง มีโอกาสเพียง 1 ใน 3E30 ของการชน หากคุณพบหนึ่งฉันขอแนะนำให้คุณรีบออกและซื้อตั๋วในการจับสลากทุกครั้งที่คุณสามารถ!
Ross Patterson

@RossPatterson สิ่งที่ฉันสงสัยเป็นพิเศษคือถ้าคุณมีคอมพิวเตอร์หลายร้อยเครื่องที่ใช้อัลกอริทึมแบบ psuedo-random ที่เหมือนกันบนฮาร์ดแวร์เดียวกันจะเพิ่มอัตราการชนกันอย่างมาก ฉันสงสัยว่ามันจะ
พอลทอมบลิ

1
@ พอล - ฉันคิดว่าเฉพาะในกรณีที่มีเอนโทรปีในกระบวนการเริ่มต้นไม่เพียงพอ - ตัวอย่างเช่นหากเมล็ดถูกสร้างขึ้นจากช่วงเวลาของวันเท่านั้นและเครื่องของคุณทั้งหมดเริ่มต้นในเวลาเดียวกัน ฉันสงสัยอย่างมากว่าการหยอดเมล็ดนั้นอ่อน - เป็นไปได้ที่จะใช้หมายเลขซีเรียลของฮาร์ดแวร์ซึ่งแน่นอนว่าจะไม่เหมือนกันสำหรับแต่ละเครื่อง
Steve314

1
อนิจจาการเพาะอาจอ่อนแอมาก ระบบลีนุกซ์ชอบที่จะสร้าง PRNG จากแหล่งสุ่มสูง (กิจกรรมไดรเวอร์อุปกรณ์ฯลฯ ) แต่ในสภาพแวดล้อมอื่น ๆ มาตรฐานคือการใช้การประทับเวลาปัจจุบันซึ่งมีเครื่องเพียงพอในการซิงค์แบบใกล้เวลาอาจเป็นปัญหาได้
Ross Patterson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.