简体   繁体   English

在Java中生成全局唯一标识符

[英]Generating a globally unique identifier in Java

Summary: I'm developing a persistent Java web application, and I need to make sure that all resources I persist have globally unique identifiers to prevent duplicates. 简介:我正在开发一个持久的Java Web应用程序,并且我需要确保持久化的所有资源都具有全局唯一的标识符,以防止重复。

The Fine Print: 细则:

  1. I'm not using an RDBMS, so I don't have any fancy sequence generators (such as the one provided by Oracle) 我没有使用RDBMS,所以没有任何特殊的序列生成器(例如Oracle提供的序列生成器)
  2. I'd like it to be fast, preferably all in memory - I'd rather not have to open up a file and increment some value 我希望它速度很快,最好是全部在内存中-我宁愿不必打开文件并增加一些值
  3. It needs to be thread safe (I'm anticipating that only one JVM at a time will need to generate IDs) 它必须是线程安全的(我预计一次只需要一个JVM即可生成ID)
  4. There needs to be consistency across instantiations of the JVM. JVM的各个实例之间必须具有一致性。 If the server shuts down and starts up, the ID generator shouldn't re-generate the same IDs it generated in previous instantiations (or at least the chance has to be really, really slim - I anticipate many millions of presisted resources) 如果服务器关闭并启动,则ID生成器不应重新生成其与先前实例化中生成的ID相同的ID(或至少机会必须非常非常小-我预计会有数以百万计的现有资源)
  5. I have seen the examples in the EJB unique ID pattern article. 我在EJB唯一ID模式文章中看到了示例。 They won't work for me (I'd rather not rely solely on System.currentTimeMillis() because we'll be persisting multiple resources per millisecond). 它们对我不起作用(我宁愿不完全依赖System.currentTimeMillis(),因为我们将每毫秒持久存储多个资源)。
  6. I have looked at the answers proposed in this question . 我已经看过这个问题提出的答案。 My concern about them is, what is the chance that I will get a duplicate ID over time? 我对它们的担心是,随着时间的流逝,我有多少机会获得重复的ID? I'm intrigued by the suggestion to use java.util.UUID for a UUID , but again, the chances of a duplicate need to be infinitesimally small. 我对将java.util.UUID用作UUID的建议很感兴趣,但同样,重复的机会必须非常小。
  7. I'm using JDK6 我正在使用JDK6

Pretty sure UUIDs are "good enough". 可以肯定的是,UUID是“足够好”的。 There are 340,282,366,920,938,463,463,374,607,431,770,000,000 UUIDs available. 有340,282,366,920,938,463,463,374,607,431,770,000,000个UUID可用。

http://www.wilybeagle.com/guid_store/guid_explain.htm http://www.wilybeagle.com/guid_store/guid_explain.htm

"To put these numbers into perspective, one's annual risk of being hit by a meteorite is estimated to be one chance in 17 billion, that means the probability is about 0.00000000006 (6 × 10−11), equivalent to the odds of creating a few tens of trillions of UUIDs in a year and having one duplicate. In other words, only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%. The probability of one duplicate would be about 50% if every person on earth owns 600 million UUIDs" “从这些数字来看,一个人每年被陨石撞击的风险估计为170亿次机会,这意味着该概率约为0.00000000006(6×10−11),等于产生几率的几率一年内有数十万亿个UUID,并且有一个重复项,也就是说,只有在接下来的100年中每秒产生10亿个UUID的情况下,仅创建一个重复项的可能性才约为50%。如果地球上每个人都拥有6亿个UUID,则大约为50%”

http://en.wikipedia.org/wiki/Universally_Unique_Identifier http://en.wikipedia.org/wiki/Universally_Unique_Identifier

If it needs to be unique per PC: you could probably use (System.currentTimeMillis() << 4) | (staticCounter++ & 15) 如果每个PC需要唯一的:您可以使用(System.currentTimeMillis() << 4) | (staticCounter++ & 15) (System.currentTimeMillis() << 4) | (staticCounter++ & 15) or something like that. (System.currentTimeMillis() << 4) | (staticCounter++ & 15)或类似的内容。

That would allow you to generate 16 per ms. 这将使您每毫秒生成16个。 If you need more, shift by 5 and and it with 31... 如果您需要更多,请按5移至31。

if it needs to be unique across multiple PCs, you should also combine in your primary network card's MAC address. 如果需要在多台PC上唯一,则还应在主网卡的MAC地址中进行组合。

edit: to clarify 编辑:澄清

private static int staticCounter=0;
private final int nBits=4;
public long getUnique() {
    return (currentTimeMillis() << nBits) | (staticCounter++ & 2^nBits-1);
}

and change nBits to the square root of the largest number you should need to generate per ms. 并将nBits更改为您需要每毫秒生成的最大数字的平方根。

It will eventually roll over. 最终它将翻转。 Probably 20 years or something with nBits at 4. 大约20年,或者nBits为4。

public class UniqueID {
    private static long startTime = System.currentTimeMillis();
    private static long id;

    public static synchronized String getUniqueID() {
        return "id." + startTime + "." + id++;
    }
}

From memory the RMI remote packages contain a UUID generator. RMI远程软件包从内存中包含一个UUID生成器。 I don't know whether thats worth looking into. 我不知道这是否值得研究。

When I've had to generate them I typically use a MD5 hashsum of the current date time, the user name and the IP address of the computer. 当不得不生成它们时,通常会使用当前日期时间,用户名和计算机的IP地址的MD5哈希值。 Basically the idea is to take everything that you can find out about the computer/person and then generate a MD5 hash of this information. 基本上,该想法是获取您可以找到的有关计算机/人的所有信息,然后生成此信息的MD5哈希。

It works really well and is incredibly fast (once you've initialised the MessageDigest for the first time). 它确实运行良好,并且运行速度非常快(一旦您第一次初始化MessageDigest)。

if you want to use a shorter and faster implementation that java UUID take a look at: 如果要使用Java UUID的更短和更快的实现,请查看:

https://code.google.com/p/spf4j/source/browse/trunk/spf4j-core/src/main/java/org/spf4j/concurrent/UIDGenerator.java https://code.google.com/p/spf4j/source/browse/trunk/spf4j-core/src/main/java/org/spf4j/concurrent/UIDGenerator.java

see the implementation choices and limitations in the javadoc. 请参阅javadoc中的实现选择和限制。

here is a unit test on how to use: 这是有关如何使用的单元测试:

https://code.google.com/p/spf4j/source/browse/trunk/spf4j-core/src/test/java/org/spf4j/concurrent/UIDGeneratorTest.java https://code.google.com/p/spf4j/source/browse/trunk/spf4j-core/src/test/java/org/spf4j/concurrent/UIDGeneratorTest.java

why not do like this 为什么不这样做

String id = Long.toString(System.currentTimeMillis()) + 
    (new Random()).nextInt(1000) + 
    (new Random()).nextInt(1000);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM