คุณถูกบังคับให้ใช้ UUID เป็นส่วนหนึ่งของการออกแบบเมื่อใด


123

ฉันไม่เห็นจุดของUUIDจริงๆ ฉันรู้ว่าความน่าจะเป็นของการชนนั้นเป็นศูนย์อย่างมีประสิทธิภาพแต่ศูนย์ที่มีประสิทธิภาพนั้นไม่ได้ใกล้เคียงกับที่เป็นไปไม่ได้เลย

ใครช่วยยกตัวอย่างที่คุณไม่มีทางเลือกอื่นนอกจากใช้ UUID ได้ไหม จากการใช้งานทั้งหมดที่ฉันเห็นฉันสามารถเห็นการออกแบบทางเลือกที่ไม่มี UUID แน่นอนว่าการออกแบบอาจซับซ้อนกว่าเล็กน้อย แต่อย่างน้อยก็ไม่มีโอกาสที่จะล้มเหลวที่ไม่ใช่ศูนย์

UUID มีกลิ่นเหมือนตัวแปรทั่วโลกสำหรับฉัน มีหลายวิธีที่ตัวแปรทั่วโลกสร้างขึ้นสำหรับการออกแบบที่เรียบง่ายขึ้น แต่การออกแบบที่ขี้เกียจ


23
ทุกอย่างมีโอกาสล้มเหลวที่ไม่ใช่ศูนย์ ฉันจะมุ่งเน้นไปที่ปัญหาที่มีแนวโน้มมากขึ้น (เช่นเกือบทุกอย่างที่คุณคิดได้) มากกว่าการชนกันของ UUIDs
DanSingerman

16
ที่จริงแล้ว "ค่าศูนย์" นั้นใกล้เคียงกับที่เป็นไปไม่ได้มาก
mqp

21
ไม่จริงมันยังห่างไกลจากความเป็นไปไม่ได้อย่างไม่มีที่สิ้นสุด
Pyrolistical

32
@Pyrolistical เมื่อคุณเริ่มใช้คำอย่าง "อินฟินิตี้" คุณก็ออกจากโลกแห่งการพัฒนาซอฟต์แวร์ ทฤษฎีวิทยาการคอมพิวเตอร์เป็นการอภิปรายที่แตกต่างจากการเขียนซอฟต์แวร์จริง
Rex M

2
ฉันจะปิดส่วนใหญ่เพราะ sha1 ของ git ทำให้ฉันเชื่อมั่นในความดีของแฮ
Pyrolistical

คำตอบ:


617

ฉันเขียนตัวสร้าง / ตัวแยกวิเคราะห์ UUID สำหรับ Ruby ดังนั้นฉันคิดว่าตัวเองมีความรู้พอสมควรในเรื่องนี้ UUID มีสี่เวอร์ชันหลัก:

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

UUID เวอร์ชัน 5 และเวอร์ชัน 3 ใช้ฟังก์ชันแฮช SHA1 และ MD5 ตามลำดับเพื่อรวมเนมสเปซกับข้อมูลที่ไม่ซ้ำกันเพื่อสร้าง UUID ตัวอย่างเช่นสิ่งนี้จะช่วยให้คุณสร้าง UUID จาก URL การชนกันจะเกิดขึ้นได้ก็ต่อเมื่อฟังก์ชันแฮชที่อยู่เบื้องหลังมีการชนกันด้วย

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

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

นอกจากนี้ 2 ^ 64 * 16 คือ 256 เอ็กซาไบต์ เช่นเดียวกับในคุณจะต้องจัดเก็บ ID ที่มีมูลค่า 256 เอ็กซาไบต์ก่อนที่คุณจะมีโอกาส 50% ที่ ID จะชนกันในพื้นที่แอปพลิเคชันเดียว


8
นี่เป็นคำอธิบายที่ดีที่สุด ฉันไม่รู้ว่าทำไมถึงไม่ได้รับการโหวตให้ติดอันดับต้น ๆ ขอชื่นชมคุณ Sporkmonger
Brad Barker

1
@Chamnap ฉันเขียน UUIDTools UUID สามารถแปลงเป็นจำนวนเต็มหรือรูปแบบไบต์ดิบและจะมีขนาดเล็กลงอย่างมากในรูปแบบไบนารี
Bob Aman

1
@Chamnap uuid.rawจะให้สตริงไบต์ hashวิธีการไม่ได้เป็นประโยชน์กับคุณ ใช้สำหรับตารางแฮชและการดำเนินการเปรียบเทียบภายใน Ruby ทุกวิธีการสำหรับการแปลงไปและกลับจากการแสดง UUID "parse"ต่างๆจะถูกกำหนดเป็นวิธีการเรียนและควรจะนำหน้าด้วย
Bob Aman

3
@BobAman ในปี 1990 ฉันมีการชนกัน 12 UUID ในระบบ Aegis กลายเป็น FPU ที่ผิดพลาด แต่คิดว่าฉันจะแจ้งให้คุณทราบว่ามันสามารถเกิดขึ้นได้ (ไม่ได้เกิดขึ้นนอกเหนือจากนั้นในช่วง 30 ปีที่ผ่านมาของการเขียนโปรแกรม) . คำอธิบายที่ดีเกินไป btw ตอนนี้เป็นโพสต์การอ้างอิง UUID defacto ของฉันที่จะให้ผู้คน :)
GMasucci

2
@kqr คุณพูดถูกจริงๆว่ามันเป็นปัญหาวันเกิดอย่างไรก็ตามสำหรับรหัส n-bit ปัญหาความขัดแย้งของวันเกิดจะลดลงเหลือ 2 ^ (n / 2) ซึ่งในกรณีนี้คือ 2 ^ 64 ตามที่ระบุไว้ในคำตอบของฉัน .
Bob Aman

69

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

ฉันได้อ่านพบว่าตามความขัดแย้งของวันเกิดโอกาสที่จะเกิดการชนกันของ UUID คือ 50% เมื่อมีการสร้าง 2 ^ 64 UUID ตอนนี้ 2 ^ 64 เป็นตัวเลขที่ค่อนข้างใหญ่ แต่โอกาสที่จะเกิดการชนกัน 50% ดูเหมือนจะเสี่ยงเกินไป (เช่นต้องมี UUID จำนวนเท่าใดก่อนที่จะมีโอกาสเกิดการชนกัน 5% แม้ว่าจะมีความน่าจะเป็นมากเกินไปก็ตาม) .

ปัญหาในการวิเคราะห์นั้นมีสองเท่า:

  1. UUIDs ไม่ได้เป็นแบบสุ่มทั้งหมด - มีส่วนประกอบหลักของ UUID ที่เป็นเวลาและ / หรือตามตำแหน่ง ดังนั้นเพื่อให้มีโอกาสเกิดการชนกัน UUID ที่ชนกันจำเป็นต้องสร้างขึ้นในเวลาเดียวกันจากเครื่องกำเนิด UUID ที่แตกต่างกัน ฉันจะบอกว่าแม้ว่าจะมีโอกาสที่สมเหตุสมผลที่อาจมีการสร้าง UUID หลายตัวในเวลาเดียวกัน แต่ก็มีขยะอื่น ๆ อีกมากพอ (รวมถึงข้อมูลตำแหน่งหรือบิตสุ่ม) ที่จะทำให้ความคล้ายคลึงกันของการชนกันระหว่าง UUID ชุดเล็ก ๆ นี้แทบจะเป็นไปไม่ได้ .

  2. พูดอย่างเคร่งครัด UUID จะต้องไม่ซ้ำกับชุดของ UUID อื่น ๆ ที่อาจนำมาเปรียบเทียบกันได้ หากคุณกำลังสร้าง UUID เพื่อใช้เป็นคีย์ฐานข้อมูลไม่สำคัญว่าที่อื่นในจักรวาลทางเลือกที่ชั่วร้ายจะใช้ UUID เดียวกันเพื่อระบุอินเทอร์เฟซ COM หรือไม่ เช่นเดียวกับที่จะไม่ทำให้เกิดความสับสนหากมีคน (หรืออย่างอื่น) ชื่อ "Michael Burr" บน Alpha-Centauri


1
ตัวอย่างที่เป็นรูปธรรม? COM / DCE UUIDs - ไม่มีอำนาจในการมอบหมายและไม่มีใครต้องการรับผิดชอบและ / หรือไม่มีใครต้องการให้มีผู้มีอำนาจ ฐานข้อมูลแบบกระจายที่ไม่มีลิงก์ที่เชื่อถือได้และไม่มีต้นแบบ
Michael Burr

3
ตัวอย่างที่เป็นรูปธรรมมากขึ้น - แอปพลิเคชันธนาคาร มีการติดตั้งศูนย์ข้อมูลหลายแห่งสำหรับแต่ละประเทศโดยศูนย์ข้อมูลแต่ละแห่งจะมีฐานข้อมูล มีการติดตั้งหลายจุดเพื่อปฏิบัติตามกฎระเบียบที่แตกต่างกัน สามารถบันทึกลูกค้าได้เพียงรายเดียวในทั้งชุดสำหรับลูกค้าทุกราย .....
Vineet Reynolds

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

เมื่อถึงเวลาที่คุณมีโอกาสทำซ้ำ 50% แสดงว่าคุณจมน้ำไปแล้ว ใครบางคนชี้ให้เห็นปริมาณที่จำเป็นเพื่อให้ได้โอกาส 0.0000001% ฐานข้อมูลที่เพิ่มขึ้นอัตโนมัติหลายฐานข้อมูลโดยเริ่มต้นที่ 1 ถึง n และเพิ่มขึ้นทีละ n ในแต่ละครั้งจะช่วยแก้ปัญหาเดียวกันได้อย่างมีประสิทธิภาพ
Gordon

2
อัตราต่อรองของการทำสำเนาคือ FAR, FAR ต่ำกว่าอัตราต่อรองของหน่วยงานกลางที่ล้มเหลวในภารกิจที่สำคัญบางประการ
std''OrgnlDave

33

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


เพิ่มเป็นคำตอบตามคำขอของ Pyrolistical
DanSingerman

16

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

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


สารละลาย. อย่าขี้เกียจและอัปเดตข้อมูลอ้างอิง ทำถูกต้อง
Pyrolistical

8
สิ่งนี้ไม่เกี่ยวข้องกับความเกียจคร้าน - หากนโยบายคือให้ ID ของไอเท็มถูกพิจารณาว่าถาวรและไม่เปลี่ยนรูป ID จะไม่เปลี่ยนแปลง ดังนั้นคุณต้องการให้ ID ไม่ซ้ำกันตั้งแต่เริ่มต้นและคุณต้องการทำเช่นนั้นโดยไม่ต้องเชื่อมต่อระบบทั้งหมดตั้งแต่เริ่มต้น
Michael Burr

คุณต้องการบริบทแล้ว หากคุณมีรหัสเฉพาะสองกลุ่มที่อาจขัดแย้งกันคุณต้องมีบริบทระดับสูงเพื่อแยกออก
Pyrolistical

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

16

ไม่จำเป็นอย่างยิ่งที่จะต้องสร้าง UUID อย่างไรก็ตามสะดวกที่จะมีมาตรฐานที่ผู้ใช้ออฟไลน์แต่ละคนสามารถสร้างกุญแจให้กับบางสิ่งได้โดยมีโอกาสเกิดการชนกันต่ำมาก

สิ่งนี้สามารถช่วยในการแก้ปัญหาการจำลองฐานข้อมูล ฯลฯ ...

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

อย่างไรก็ตามคำเกี่ยวกับความน่าจะเป็นของการชนกันนำมาจาก Wikipedia:

ในการพิจารณาตัวเลขเหล่านี้ในมุมมองความเสี่ยงต่อปีของการถูกอุกกาบาตชนนั้นคาดว่าจะมีโอกาสเพียงครั้งเดียวใน 17 พันล้านเท่ากับโอกาสในการสร้าง UUID ไม่กี่สิบล้านล้านในหนึ่งปีและมีหนึ่งรายการซ้ำ กล่าวอีกนัยหนึ่งหลังจากสร้าง 1 พันล้าน UUID ทุกวินาทีในอีก 100 ปีข้างหน้าความน่าจะเป็นที่จะสร้างรายการที่ซ้ำกันเพียง 1 รายการจะอยู่ที่ประมาณ 50%


4
ง่ายๆอย่าให้ผู้ใช้ออฟไลน์สร้างคีย์ กำหนดคีย์ชั่วคราวไว้จนกว่าระบบจะออนไลน์เพื่อให้สามารถสร้างคีย์จริงได้
Pyrolistical

นี่เป็นคำตอบที่มีประโยชน์มากในความคิดของฉัน ... กำลังจะเสนอการเปรียบเทียบบางอย่างกับความน่าจะเป็นของตัวเองเนื่องจากดูเหมือนว่า OP จะไม่ค่อยเข้าใจความหมาย แต่ดูเหมือนคุณจะทำเช่นนั้นแล้ว
Noldorin

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

นั่นยุติธรรมเพียงพอตราบใดที่คุณเห็นว่าความน่าจะเป็นต่ำนั้นจำเป็นต้องได้รับการพิจารณาในสถานการณ์ที่รุนแรงที่สุดด้วยเช่นกันตอนนี้ฉันจะคิดว่าคุณทำ
Noldorin

13

ตัวอย่างคลาสสิกคือเมื่อคุณกำลังจำลองระหว่างสองฐานข้อมูล

DB (A) แทรกเร็กคอร์ดที่มี int ID 10 และในเวลาเดียวกัน DB (B) สร้างเร็กคอร์ด aa ด้วยใน ID 10 นี่คือการชนกัน

ด้วย UUID สิ่งนี้จะไม่เกิดขึ้นเนื่องจากจะไม่ตรงกัน (เกือบจะแน่นอน)


1
ตกลงจากนั้นให้ DB A ใช้แม้แต่ ID และ DB B ใช้รหัสคี่ เสร็จแล้วไม่มี UUID
Pyrolistical

2
ด้วยสาม DB ให้ใช้ 3 ทวีคูณ LOL
Jhonny D. Cano -Leftware -

20
หากคุณใช้ 2/3 / ทวีคูณใด ๆ จะเกิดอะไรขึ้นเมื่อคุณเพิ่มเซิร์ฟเวอร์ใหม่ในการผสมในภายหลัง คุณต้องประสานงานสวิตช์เพื่อที่คุณจะใช้ n + 1 ทวีคูณบนเซิร์ฟเวอร์ใหม่และย้ายเซิร์ฟเวอร์เก่าทั้งหมดไปยังอัลกอริทึมใหม่และคุณต้องปิดทุกอย่างในขณะที่คุณทำสิ่งนี้เพื่อหลีกเลี่ยงการชนกันระหว่าง สวิตช์อัลกอริทึม หรือ ... คุณสามารถใช้ UUID เช่น EVERYONE ELSE
Bob Aman

3
มันยิ่งแย่ไปกว่านั้นเพราะคุณจะแยกความแตกต่างระหว่างทวีคูณของ 2 และทวีคูณของ 4 ได้อย่างไร? หรือทวีคูณของ 3 เทียบกับทวีคูณของ 6? ในความเป็นจริงคุณจะต้องยึดติดกับจำนวนเฉพาะหลายตัว Blech! เพียงแค่ใช้ UUID ก็ใช้งานได้ Microsoft, Apple และอื่น ๆ อีกนับไม่ถ้วนไว้วางใจและไว้วางใจพวกเขา
sidewinderguy

2
@sidewinderguy ใน GUID เราเชื่อมั่น! :)
Ron Klein

13

นอกจากนี้ยังมีความน่าจะเป็นที่ไม่ใช่ศูนย์ที่ทุกอนุภาคในร่างกายของคุณจะเจาะทะลุเก้าอี้ที่คุณนั่งอยู่พร้อม ๆ กันและจู่ๆคุณก็จะพบว่าตัวเองนั่งอยู่บนพื้น

คุณกังวลเกี่ยวกับเรื่องนั้นหรือไม่?


7
ไม่แน่นอนนั่นไม่ใช่สิ่งที่ฉันควบคุมได้ แต่ฉันออกแบบได้
Pyrolistical

4
@Pyrolistical เป็นเช่นนั้นจริง ๆ ฉันหมายถึงเหตุผลที่คุณไม่ต้องกังวลเกี่ยวกับเรื่องนั้นจริงๆ แล้วคุณค่อนข้างแปลก และยิ่งไปกว่านั้นคุณทำไม่ถูก คุณสามารถควบคุมมันได้ หากคุณมีน้ำหนักเพิ่มขึ้นไม่กี่ปอนด์คุณจะลดความน่าจะเป็นของเหตุการณ์ดังกล่าวลงอย่างมาก คุณคิดว่าคุณควรเพิ่มน้ำหนักแล้วหรือยัง? :-)
Veky

8

ฉันมีแผนในการหลีกเลี่ยง UUID ตั้งค่าเซิร์ฟเวอร์ที่ใดที่หนึ่งและมีเพื่อให้ทุกครั้งที่ซอฟต์แวร์บางชิ้นต้องการตัวระบุที่ไม่ซ้ำกันในระดับสากลพวกเขาจะติดต่อกับเซิร์ฟเวอร์นั้นและส่งมอบให้ ! ง่าย

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

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


2
จริงๆแล้วประเด็นทั้งหมดของการประดิษฐ์ UUIDs คือการหลีกเลี่ยงแนวทางของคุณ หากคุณค้นคว้าประวัติของ UUID คุณจะเห็นว่าได้มาจากการทดลองแรกสุดในการสร้างเครือข่ายคอมพิวเตอร์ที่ซับซ้อนและมีความหมาย พวกเขารู้ดีว่าเครือข่ายไม่น่าเชื่อถือและซับซ้อนโดยเนื้อแท้ UUID เป็นคำตอบสำหรับคำถามเกี่ยวกับวิธีประสานข้อมูลระหว่างคอมพิวเตอร์เมื่อคุณรู้ว่าไม่สามารถสื่อสารได้ตลอดเวลา
Basil Bourque

7
@BasilBourque ฉันใช้คำพูดถากถางในย่อหน้าแรกนั้นในกรณีที่มันไม่ชัดเจน
Donal Fellows

5

ฉันไม่ได้รับการพูดถึงทั้งหมดเกี่ยวกับโอกาสที่จะเกิดการปะทะกัน ฉันไม่สนใจเรื่องการชนกัน ฉันสนใจเกี่ยวกับประสิทธิภาพแม้ว่า

https://dba.stackexchange.com/a/119129/33649

UUID เป็นภัยพิบัติด้านประสิทธิภาพสำหรับตารางขนาดใหญ่มาก (200K แถวไม่ "ใหญ่มาก")

# 3 ของคุณแย่มากเมื่อ CHARCTER SET เป็น utf8 - CHAR (36) ครอบครอง 108 ไบต์!

UUID (GUID) เป็นแบบ "สุ่ม" มาก การใช้เป็นคีย์ UNIQUE หรือ PRIMARY บนตารางขนาดใหญ่นั้นไม่มีประสิทธิภาพมาก เนื่องจากต้องกระโดดไปรอบ ๆ ตาราง / ดัชนีทุกครั้งที่คุณใส่ UUID ใหม่หรือเลือกโดย UUID เมื่อตาราง / ดัชนีมีขนาดใหญ่เกินกว่าที่จะใส่แคชได้ (โปรดดูที่ innodb_buffer_pool_size ซึ่งต้องมีขนาดเล็กกว่า RAM โดยทั่วไป 70%) UUID "ถัดไป" อาจไม่ถูกแคชดังนั้นจึงทำให้ดิสก์ถูกโจมตีช้า เมื่อตาราง / ดัชนีมีขนาดใหญ่เป็น 20 เท่าของแคชจะมีการแคชเฉพาะ 1 / 20th (5%) ของ Hit เท่านั้นคุณจะถูกผูกไว้กับ I / O

ดังนั้นอย่าใช้ UUID เว้นแต่อย่างใดอย่างหนึ่ง

คุณมีตาราง "เล็ก" หรือคุณต้องการจริงๆเนื่องจากการสร้างรหัสเฉพาะจากที่ต่างๆ (และยังไม่ได้หาวิธีอื่นในการทำ) เพิ่มเติมเกี่ยวกับ UUIDs: http://mysql.rjweb.org/doc.php/uuid (ประกอบด้วยฟังก์ชันสำหรับการแปลงระหว่าง UUID 36-char มาตรฐานและ BINARY (16))

การมีทั้ง UNIQUE AUTO_INCREMENT และ UNIQUE UUID ในตารางเดียวกันเป็นการสิ้นเปลือง

เมื่อเกิด INSERT จะต้องตรวจสอบคีย์เฉพาะ / คีย์หลักทั้งหมดเพื่อหารายการที่ซ้ำกัน คีย์เฉพาะอย่างใดอย่างหนึ่งก็เพียงพอสำหรับข้อกำหนดของ InnoDB ในการมีคีย์หลัก ไบนารี (16) (16 ไบต์) ค่อนข้างใหญ่ (ข้อโต้แย้งในการสร้าง PK) แต่ก็ไม่ได้แย่ขนาดนั้น ความใหญ่มีความสำคัญเมื่อคุณมีคีย์รอง InnoDB จะจัดการ PK อย่างเงียบ ๆ ที่ส่วนท้ายของคีย์รองแต่ละอัน บทเรียนหลักที่นี่คือการลดจำนวนคีย์รองโดยเฉพาะอย่างยิ่งสำหรับตารางขนาดใหญ่มาก สำหรับการเปรียบเทียบ: INT UNSIGNED คือ 4 ไบต์โดยมีช่วง 0..4 พันล้าน BIGINT คือ 8 ไบต์


4

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


3

บน UUID == การออกแบบที่ขี้เกียจ

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


1

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


แน่นอนว่าบุคคลที่สามที่บังคับให้คุณใช้ UUID เป็นอีกปัญหาหนึ่งที่ฉันไม่ต้องการแก้ไข สมมติว่าคุณสามารถควบคุมการใช้ UUID ได้หรือไม่
Pyrolistical

"จำนวนเต็มยาว" (128 บิต) คือสิ่งที่ UUID คืออะไร แสดงเป็นเพียงสตริงสำหรับการบริโภคของมนุษย์ บางครั้งมันอาจถูกส่งด้วยวิธีนั้น แต่สำหรับการจัดเก็บและการจัดทำดัชนีนั้นจะเร็วกว่าในรูปแบบจำนวนเต็มอย่างที่คุณพบ
Nicole

1

การใช้อัลกอริทึมเวอร์ชัน 1 ดูเหมือนว่าจะเป็นไปไม่ได้ที่จะเกิดการชนกันภายใต้ข้อ จำกัด ที่น้อยกว่า 10 UUIDs ต่อมิลลิวินาทีถูกสร้างขึ้นจากที่อยู่ MAC เดียวกัน

ตามแนวคิดโครงร่างการสร้างดั้งเดิม (เวอร์ชัน 1) สำหรับ UUID คือการเชื่อมต่อเวอร์ชัน UUID กับที่อยู่ MAC ของคอมพิวเตอร์ที่สร้าง UUID และด้วยจำนวนช่วงเวลา 100 นาโนวินาทีนับตั้งแต่การใช้ปฏิทินเกรกอเรียนในตะวันตก . ในทางปฏิบัติอัลกอริทึมจริงมีความซับซ้อนมากขึ้น โครงการนี้ได้รับการวิพากษ์วิจารณ์ว่ามันไม่เพียงพอ 'ทึบแสง'; จะเปิดเผยทั้งข้อมูลประจำตัวของคอมพิวเตอร์ที่สร้าง UUID และเวลาที่ทำเช่นนั้น

มีคนแก้ไขให้ฉันถ้าฉันตีความวิธีการทำงานผิด


มีหลายเวอร์ชันและระบบซอฟต์แวร์จำนวนมาก (เช่น Java) ไม่สามารถใช้เวอร์ชัน 1 ได้เนื่องจากไม่มีวิธี Java บริสุทธิ์ในการเข้าถึงที่อยู่ mac
Pyrolistical

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

ตามที่กล่าวไว้ในคำตอบของฉันหากคุณไม่สามารถรับที่อยู่ MAC สำหรับ UUID เวอร์ชัน 1 คุณใช้ 6 ไบต์แบบสุ่มแทนตามส่วน 4.5 ของ RFC 4122 ดังนั้นแม้ว่าคุณจะไม่ต้องการใช้อย่างใดอย่างหนึ่ง วิธีแก้ปัญหาสองประการสำหรับ Java คุณยังคงสามารถสร้าง UUID เวอร์ชัน 1 ที่ถูกต้องได้
Bob Aman

MS GUID เป็นเพียงตัวเลขสุ่ม พวกเขาไม่มีส่วน MAC อีกต่อไปเพราะนั่นทำให้สามารถทำวิศวกรรมย้อนกลับที่อยู่ MAC ของเซิร์ฟเวอร์ได้ (ซึ่งกลายเป็นอันตรายมาก)
Stefan Steiger

1

สำหรับผู้ที่บอกว่า UUID เป็นการออกแบบที่ไม่ดีเพราะอาจชนกันได้ (ด้วยความเป็นไปได้เล็กน้อยที่น่าขัน) ในขณะที่คีย์ที่สร้างฐานข้อมูลของคุณจะไม่ ... คุณรู้ว่ามีโอกาสเกิดข้อผิดพลาดของมนุษย์ที่ทำให้เกิดการชนกันในคีย์ที่สร้างขึ้นเนื่องจาก DB - สำหรับความต้องการคือ FAR FAR FAR สูงกว่าโอกาสในการชนกันของ UUID4 เรารู้ว่าถ้าสร้างฐานข้อมูลใหม่มันจะเริ่มรหัสที่ 1 อีกครั้งและมีกี่คนที่ต้องสร้างตารางใหม่เมื่อเราแน่ใจว่าเราไม่จำเป็นต้องทำอีกแล้ว ฉันจะเอาเงินไปใช้กับความปลอดภัยของ UUID เมื่อสิ่งต่างๆเริ่มผิดพลาดโดยที่ไม่รู้จักไม่รู้จักวันใด ๆ


0

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

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

วิธีที่ "ชัดเจน" ที่สุดในการหลีกเลี่ยงการชนกันคือการปล่อยให้เซิร์ฟเวอร์เดียวสร้าง ID ที่ไม่ซ้ำกันในทุกๆส่วนแทรกซึ่งเห็นได้ชัดว่าสร้างปัญหาด้านประสิทธิภาพที่รุนแรงและไม่ได้แก้ปัญหาการสร้างออฟไลน์เลย อุ่ย

โซลูชันที่ "ชัดเจน" อื่น ๆ คือหน่วยงานกลางที่ส่งบล็อกของหมายเลขเฉพาะล่วงหน้าซึ่งโดยพื้นฐานแล้ว UUID V1 ทำโดยใช้ที่อยู่ MAC ของเครื่องสร้าง (ผ่าน IEEE OUI) แต่ที่อยู่ MAC ที่ซ้ำกันจะเกิดขึ้นได้เนื่องจากหน่วยงานกลางทุกหน่วยงานในที่สุดดังนั้นในทางปฏิบัติสิ่งนี้มีโอกาสมากกว่าการชนกันของ UUID V4 อุ่ย

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

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


-10

UUIDs รวบรวมแนวทางปฏิบัติในการเข้ารหัสที่ไม่ดีทั้งหมดที่เกี่ยวข้องกับตัวแปรทั่วโลกยิ่งแย่ไปกว่านั้นเนื่องจากเป็นตัวแปร superglobal ซึ่งสามารถกระจายไปตามชุดต่างๆได้

เมื่อเร็ว ๆ นี้พบปัญหาดังกล่าวด้วยการเปลี่ยนเครื่องพิมพ์ที่มีรุ่นทดแทนที่แน่นอนและพบว่าไม่มีซอฟต์แวร์ไคลเอ็นต์ใดทำงานได้


2
ดีใจที่เราอยู่ในสังคมที่ยังคงมุ่งเน้นไปที่ข้อเท็จจริงซึ่งตรงข้ามกับความคิดเห็นแบบสุ่มมิฉะนั้นพวกเราทุกคนที่มีสแต็กล้นจะต้องออกจากงาน :)
Makarand
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.