หากฉันใช้ความLong uuid = UUID.randomUUID().getMostSignificantBits()
เป็นไปได้ที่จะได้รับการชน มันตัดบิตที่สำคัญน้อยที่สุดออกไปดังนั้นจึงมีความเป็นไปได้ที่คุณจะชนกันใช่ไหม?
หากฉันใช้ความLong uuid = UUID.randomUUID().getMostSignificantBits()
เป็นไปได้ที่จะได้รับการชน มันตัดบิตที่สำคัญน้อยที่สุดออกไปดังนั้นจึงมีความเป็นไปได้ที่คุณจะชนกันใช่ไหม?
คำตอบ:
ตามเอกสารคู่มือเมธอดสแตติกUUID.randomUUID()
สร้างชนิด UUID 4
ซึ่งหมายความว่ามีการใช้หกบิตสำหรับข้อมูลบางประเภทและ 122 บิตที่เหลือจะถูกกำหนดแบบสุ่ม
บิตที่ไม่ใช่แบบสุ่มจำนวนหกบิตถูกกระจายด้วยสี่ในครึ่งที่สำคัญที่สุดของ UUID และสองในครึ่งที่สำคัญน้อยที่สุด ดังนั้นครึ่งที่สำคัญที่สุดของ UUID ของคุณจะมีการสุ่ม 60 บิตซึ่งหมายความว่าคุณโดยเฉลี่ยต้องสร้าง 2 ^ 30 UUID เพื่อให้ได้รับการชนกัน (เทียบกับ 2 ^ 61 สำหรับ UUID เต็มรูปแบบ)
ดังนั้นฉันจะบอกว่าคุณค่อนข้างปลอดภัย อย่างไรก็ตามโปรดทราบว่าสิ่งนี้ไม่เป็นความจริงสำหรับ UUID ประเภทอื่นเช่นที่ Carl Seleborg กล่าวถึง
บังเอิญคุณจะดีขึ้นเล็กน้อยโดยใช้ครึ่งหนึ่งที่สำคัญน้อยที่สุดของ UUID (หรือเพียงแค่สร้างการสุ่มระยะยาวโดยใช้ SecureRandom)
เรย์มอนด์เฉินมีโพสต์บล็อกที่ยอดเยี่ยมจริงๆในนี้:
ฉันคิดว่านี่เป็นตัวอย่างที่ดีที่สุดสำหรับการใช้ randomUUID:
คุณจะดีกว่าเพียงแค่สร้างค่ายาวแบบสุ่มจากนั้นบิตทั้งหมดจะถูกสุ่ม ใน Java 6, Random ใหม่ () ใช้ System.nanoTime () บวกตัวนับเป็นเมล็ด
มีเอกลักษณ์ที่แตกต่างกันไป
หากคุณต้องการความเป็นเอกลักษณ์ในหลาย ๆ เครื่องคุณอาจมีตารางฐานข้อมูลส่วนกลางสำหรับการจัดสรรรหัสที่ไม่ซ้ำกันหรือแม้กระทั่งรหัสที่เป็นเอกลักษณ์
หากคุณต้องการมีเอกลักษณ์ในหนึ่งแอพคุณสามารถมีตัวนับ (หรือตัวนับที่เริ่มต้นจาก currentTimeMillis () * 1,000 หรือ nanoTime () ขึ้นอยู่กับความต้องการของคุณ)
ใช้เวลาYYYYDDDD
(ปี + วันแห่งปี) เป็นคำนำหน้า สิ่งนี้จะลดการกระจายตัวของฐานข้อมูลในตารางและดัชนี byte[40]
วิธีนี้ผลตอบแทน ฉันใช้มันในสภาพแวดล้อมไฮบริดที่ Active Directory SID ( varbinary(85)
) เป็นกุญแจสำคัญสำหรับผู้ใช้ LDAP และใช้ ID ที่สร้างขึ้นอัตโนมัติของแอปพลิเคชันสำหรับผู้ใช้ที่ไม่ใช่ LDAP นอกจากนี้ธุรกรรมจำนวนมากต่อวันในตารางธุรกรรม (อุตสาหกรรมการธนาคาร) ไม่สามารถใช้Int
ประเภทมาตรฐานสำหรับคีย์ได้
private static final DecimalFormat timeFormat4 = new DecimalFormat("0000;0000");
public static byte[] getSidWithCalendar() {
Calendar cal = Calendar.getInstance();
String val = String.valueOf(cal.get(Calendar.YEAR));
val += timeFormat4.format(cal.get(Calendar.DAY_OF_YEAR));
val += UUID.randomUUID().toString().replaceAll("-", "");
return val.getBytes();
}