在Java中使用UUID的最高有效位进行冲突的可能性
如果我使用Long uuid = UUID.randomUUID().getMostSignificantBits()
多大可能会发生冲突。 它切断了最不重要的位,所以有可能碰到碰撞,对吧?
根据文档 ,静态方法UUID.randomUUID()
生成types4的UUID。
这意味着一些types信息使用六位,其余的122位是随机分配的。
六个非随机比特在UUID的最高有效半部分中分布有四个,而在最低有效半部分中有两个。 因此,最重要的一半UUID包含60位随机性,这意味着您平均需要生成2 ^ 30个UUID才能发生冲突(与完整UUID的2 ^ 61相比)。
所以我会说,你是相当安全的。 但请注意,对于其他types的UUID,这是绝对不正确的,正如Carl Seleborg提到的那样。
顺便说一下,使用UUID的最低有效部分(或者只是使用SecureRandom生成一个随机长度),会稍微好一些。
Raymond Chen在这方面有非常出色的博客文章:
GUID是全局唯一的,但GUID的子string不是
我认为这是使用randomUUID最好的例子:
你最好只生成一个随机的长值,然后所有的位都是随机的。 在Java 6中,新的Random()使用System.nanoTime()加上一个计数器作为种子。
有不同程度的独特性。
如果您需要跨越多台机器的唯一性,您可以有一个中央数据库表来分配唯一的ID,甚至是批次的唯一ID。
如果您只需要在一个应用程序中具有唯一性,您可以只有一个计数器(或根据您的要求从currentTimeMillis()* 1000或nanoTime()开始的计数器)
使用时间YYYYDDDD
(年+日年)作为前缀。 这可以减less表和索引中的数据库碎片。 这个方法返回byte[40]
。 我在混合环境中使用它,Active Directory SID( varbinary(85)
)是LDAP用户的密钥,应用程序自动生成的ID用于非LDAP用户。 此外,交易表(银行业)每天大量的交易不能使用标准的Int
types的密钥
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(); }