在Java中生成全局唯一标识符
-
08-07-2019 - |
题
摘要:我正在开发一个持久的Java Web应用程序,我需要确保我持有的所有资源都具有全局唯一标识符以防止重复。
精美打印:
- 我没有使用RDBMS,所以我没有任何花哨的序列生成器(例如Oracle提供的生成器)
- 我希望它很快,最好全部在内存中 - 我宁愿不打开文件并增加一些值
- 它需要是线程安全的(我预计一次只有一个JVM需要生成ID)
- 需要在JVM的实例化之间保持一致。如果服务器关闭并启动,ID生成器不应该重新生成它在先前实例化中生成的相同ID(或者至少机会必须非常,非常小 - 我预计会有数百万个预先存储的资源)
- 我看过EJB唯一ID模式文章中的示例。它们对我不起作用(我宁愿不仅仅依靠System.currentTimeMillis(),因为我们将每毫秒保持多个资源)。
- 我查看了这提出的答案问题。我对它们的关注是,随着时间的推移,我将获得重复ID的可能性是多少?我对使用 java的建议很感兴趣 UUID 的.util.UUID ,但同样重复的可能性需要无限小。
- 我正在使用JDK6 醇>
解决方案
非常确定UUID <!>“足够好<!>”;有340,282,366,920,938,463,463,374,607,431,770,000,000 UUID可用。
http://www.wilybeagle.com/guid_store/guid_explain.htm
<!>“为了正确看待这些数字,每年被陨石击中的风险估计为170亿的一次机会,这意味着概率约为0.00000000006(6 <!>#215; 10 <!>#8722; 11),相当于在一年内创造几十万亿UUID并且有一个副本的几率。换句话说,只有在接下来的100年中每秒产生10亿UUID之后,创建一个副本的概率大约为50%。如果地球上的每个人拥有6亿UUID,则一次重复的概率约为50%>>
其他提示
public class UniqueID {
private static long startTime = System.currentTimeMillis();
private static long id;
public static synchronized String getUniqueID() {
return "id." + startTime + "." + id++;
}
}
如果它需要每台PC都是唯一的:你可以使用(System.currentTimeMillis() << 4) | (staticCounter++ & 15)
或类似的东西。
这将允许您每毫秒生成16个。如果您需要更多,请移动5并使用31 ...
如果它需要在多台PC上是唯一的,您还应该在主网卡的MAC地址中合并。
编辑:澄清
private static int staticCounter=0;
private final int nBits=4;
public long getUnique() {
return (currentTimeMillis() << nBits) | (staticCounter++ & 2^nBits-1);
}
并将nBits更改为每ms应生成的最大数字的平方根。
它最终会翻身。可能是20年或者nBits为4的东西。
从内存中,RMI远程包包含一个UUID生成器。我不知道那是否值得研究。
当我必须生成它们时,我通常使用当前日期时间的MD5哈希值,用户名和计算机的IP地址。基本上,我们的想法是获取有关计算机/人员的所有信息,然后生成此信息的MD5哈希值。
它运行得非常好并且非常快(一旦你第一次初始化MessageDigest)。
为什么不这样做
String id = Long.toString(System.currentTimeMillis()) +
(new Random()).nextInt(1000) +
(new Random()).nextInt(1000);
如果你想使用java UUID看到的更短更快的实现:
查看javadoc中的实现选择和限制。
这是一个关于如何使用的单元测试: