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

发布于 2024-07-06 21:40:16 字数 924 浏览 9 评论 0原文

摘要:我正在开发一个持久性 Java Web 应用程序,我需要确保我保留的所有资源都具有全局唯一标识符以防止重复。

细则:

  1. 我没有使用 RDBMS,因此我没有任何花哨的序列生成器(例如 Oracle 提供的序列生成器),
  2. 我希望它能够快速运行,最好全部集成内存 - 我不想打开一个文件并增加一些值
  3. 它需要是线程安全的(我预计一次只有一个 JVM 需要生成 ID)
  4. 实例化之间需要保持一致性JVM。 如果服务器关闭并启动,ID 生成器不应该重新生成在先前实例化中生成的相同 ID(或者至少机会必须非常非常小 - 我预计会有数百万个保留资源
  5. )请参阅 EJB 唯一 ID 模式文章中的示例。 它们对我不起作用(我不想仅仅依赖 System.currentTimeMillis(),因为我们将每毫秒保留多个资源)。
  6. 我查看了这个问题。 我担心的是,随着时间的推移,我获得重复 ID 的可能性有多大? 我对使用 java 的建议很感兴趣.util.UUID 对于 UUID,但同样,重复的可能性需要无限小。
  7. 我使用的是JDK6

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.

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)
  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)
  4. There needs to be consistency across instantiations of the 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)
  5. I have seen the examples in the EJB unique ID pattern article. They won't work for me (I'd rather not rely solely on System.currentTimeMillis() because we'll be persisting multiple resources per millisecond).
  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? 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.
  7. I'm using JDK6

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

紫轩蝶泪 2024-07-13 21:40:16

可以肯定 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 × 10−11),相当于产生数十万亿个陨石的几率一年内产生一个重复的 UUID 换句话说,只有在接下来的 100 年中每秒生成 10 亿个 UUID 后,仅创建一个重复的概率才会约为 50%。产生一个重复的概率约为 50%。如果地球上每个人都拥有 6 亿个 UUID”

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

Pretty sure UUIDs are "good enough". There are 340,282,366,920,938,463,463,374,607,431,770,000,000 UUIDs available.

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"

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

倒数 2024-07-13 21:40:16
public class UniqueID {
    private static long startTime = System.currentTimeMillis();
    private static long id;

    public static synchronized String getUniqueID() {
        return "id." + startTime + "." + id++;
    }
}
public class UniqueID {
    private static long startTime = System.currentTimeMillis();
    private static long id;

    public static synchronized String getUniqueID() {
        return "id." + startTime + "." + id++;
    }
}
罪歌 2024-07-13 21:40:16

如果它需要在每台 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 更改为每毫秒需要生成的最大数字的平方根。

它最终会翻过来。 nBits 为 4 时,可能需要 20 年左右。

If it needs to be unique per PC: you could probably use (System.currentTimeMillis() << 4) | (staticCounter++ & 15) or something like that.

That would allow you to generate 16 per ms. If you need more, shift by 5 and and it with 31...

if it needs to be unique across multiple PCs, you should also combine in your primary network card's MAC address.

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.

It will eventually roll over. Probably 20 years or something with nBits at 4.

口干舌燥 2024-07-13 21:40:16

从内存中,RMI 远程包包含一个 UUID 生成器。 我不知道这是否值得研究。

当我必须生成它们时,我通常使用当前日期时间、用户名和计算机 IP 地址的 MD5 哈希和。 基本上,这个想法是获取有关计算机/人的所有信息,然后生成该信息的 MD5 哈希值。

它工作得非常好并且速度快得令人难以置信(一旦您第一次初始化了 MessageDigest)。

From memory the RMI remote packages contain a UUID generator. 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. 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.

It works really well and is incredibly fast (once you've initialised the MessageDigest for the first time).

海的爱人是光 2024-07-13 21:40:16

为什么不这样做

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

why not do like this

String id = Long.toString(System.currentTimeMillis()) + 
    (new Random()).nextInt(1000) + 
    (new Random()).nextInt(1000);
染年凉城似染瑾 2024-07-13 21:40:16

如果您想使用 java UUID 的更短更快的实现,请查看:

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

请参阅 javadoc 中的实现选择和限制。

这是有关如何使用的单元测试:

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

if you want to use a shorter and faster implementation that java UUID take a look at:

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.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文