在 Java 中使用 UUID 的最高有效位发生冲突的可能性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/325443/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Likelihood of collision using most significant bits of a UUID in Java
提问by dlinsin
If I'm using Long uuid = UUID.randomUUID().getMostSignificantBits()
how likely is it to get a collision. It cuts off the least significant bits, so there is a possibility that you run into a collision, right?
如果我正在使用Long uuid = UUID.randomUUID().getMostSignificantBits()
它发生碰撞的可能性有多大。它切断了最低有效位,因此您有可能遇到冲突,对吗?
采纳答案by Rasmus Faber
According to the documentation, the static method UUID.randomUUID()
generates a type 4 UUID.
根据文档,静态方法UUID.randomUUID()
生成类型 4 UUID。
This means that six bits are used for some type information and the remaining 122 bits are assigned randomly.
这意味着 6 位用于某些类型信息,其余 122 位是随机分配的。
The six non-random bits are distributed with four in the most significant half of the UUID and two in the least significant half. So the most significant half of your UUID contains 60 bits of randomness, which means you on average need to generate 2^30 UUIDs to get a collision (compared to 2^61 for the full UUID).
六个非随机位分布在 UUID 的最高有效半部中的四个和最低有效半部中的两个。因此,您的 UUID 的最重要的一半包含 60 位随机性,这意味着您平均需要生成 2^30 个 UUID 才能发生碰撞(与完整 UUID 的 2^61 相比)。
So I would say that you are rather safe. Note, however that this is absolutely not true for other types of UUIDs, as Carl Seleborg mentions.
所以我会说你是相当安全的。但是请注意,正如 Carl Seleborg 所提到的,对于其他类型的 UUID,这绝对不是真的。
Incidentally, you would be slightly better off by using the least significant half of the UUID (or just generating a random long using SecureRandom).
顺便说一句,使用 UUID 的最低有效一半(或仅使用 SecureRandom 生成随机长)会稍微好一点。
回答by Carl Seleborg
Raymond Chen has a really excellent blog post on this:
Raymond Chen 在这方面有一篇非常出色的博客文章:
回答by Peter Lawrey
You are better off just generating a random long value, then all the bits are random. In Java 6, new Random() uses the System.nanoTime() plus a counter as a seed.
您最好只生成一个随机长值,然后所有位都是随机的。在 Java 6 中, new Random() 使用 System.nanoTime() 加上一个计数器作为种子。
There are different levels of uniqueness.
有不同程度的独特性。
If you need uniqueness across many machines, you could have a central database table for allocating unique ids, or even batches of unique ids.
如果您需要跨多台机器的唯一性,您可以拥有一个中央数据库表来分配唯一 ID,甚至是成批的唯一 ID。
If you just need to have uniqueness in one app you can just have a counter (or a counter which starts from the currentTimeMillis()*1000 or nanoTime() depending on your requirements)
如果您只需要在一个应用程序中具有唯一性,您可以拥有一个计数器(或从 currentTimeMillis()*1000 或 nanoTime() 开始的计数器,具体取决于您的要求)
回答by Kannika
I thinks this is the best example for using randomUUID :
我认为这是使用 randomUUID 的最佳示例:
回答by Dr Bob
Use Time YYYYDDDD
(Year + Day of Year) as prefix. This decreases database fragmentation in tables and indexes. This method returns byte[40]
. I used it in a hybrid environment where the Active Directory SID (varbinary(85)
) is the key for LDAP users and an application auto-generated ID is used for non-LDAP Users. Also the large number of transactions per day in transactional tables (Banking Industry) cannot use standard Int
types for Keys
使用时间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();
}