【问题标题】:Safe to use System.currentTimeMillis() to generate a unique database ID?使用 System.currentTimeMillis() 生成唯一的数据库 ID 是否安全?
【发布时间】:2011-06-20 08:49:53
【问题描述】:

我在 Java 中使用 System.currentTimeMillis()(它返回一个 long 整数)为数据库实体生成唯一 ID,因为我认为这些时间不可能在任何时候重叠。

这是一个安全的假设吗?

例如,目前我得到这个:

1296691225227

【问题讨论】:

    标签: java time uniqueidentifier


    【解决方案1】:

    不,这不安全。一毫秒在 CPU 周期中是很长的时间(它们以每秒数十亿个周期而不是数千个周期运行),因此如果一次有多个请求或多个线程都尝试创建数据库条目,它们将看到相同的 CPU 时间和最终会发生碰撞键。如果系统时钟以某种方式被重置或更改为更早的时间,您也会遇到麻烦。

    【讨论】:

    • 另外值得注意的是,虽然毫秒定时器的最小粒度理论上是1ms,但实际的粒度可能更大。我使用的是 20 毫秒的系统。
    • 更不用说像 ntp 让你的时钟倒退了。
    • 什么是最小粒度?如何检查我的系统的价值?
    【解决方案2】:

    您不太可能会发生冲突,是的(除非您处于高负载系统中,在这种情况下它非常很可能),但仍有可能。

    不过,Java 有一个生成唯一标识符的现有机制 - java.util.UUID。它具有生成随机 ID 的方法。

    我强烈建议改用它。

    【讨论】:

    • 就失败概率而言,我怀疑毫秒方法能否在单元测试中存活下来。
    • @Dolph - 或系统负载测试。当然不应该……如果你做得对的话。
    • 我非常喜欢 UUID,但是它效率很低(理解困难的方式......)通常的存储方式是 UUID.toString(),它是可怕的 36 字节长(通常映射到类似的东西varchar(36))。数据库索引应该保存在内存中——索引越大,需要的内存越多,索引也会变慢,等等。我建议使用一些带集群位和long id 的高低方案。
    • @bestsss:您能否澄清一下您提出的集群位方案?
    【解决方案3】:

    如果您的代码曾经在集群环境中运行,则会增加您发生 id 冲突的几率。

    大多数 JPA 数据库都有自己生成唯一 ID 的方法。

    http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-26
      相关资源
      最近更新 更多