使用System.currentTimeMillis()生成唯一的数据库ID是否安全?

14

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

这是一个安全的假设吗?

例如,目前我得到了以下时间戳:

1296691225227
3个回答

20

不,这样是不安全的。在CPU周期中,一毫秒的时间很长(它们每秒运行数十亿个周期,而不是数千个),因此如果同时发出多个请求或多个线程都尝试创建数据库条目,则它们将看到相同的CPU时间,并且会导致键冲突。如果系统时钟被重置或更改为早期时间,也会遇到麻烦。


5
值得注意的是,尽管毫秒计时器的最小粒度理论上为1毫秒,实际粒度可能更大。我曾经使用过的系统粒度为20毫秒。 - Stephen C
1
更不用说像ntp这样会将您的时钟向后移动的东西了。 - jtahlborn
什么是最小粒度?我如何检查我的系统的值? - Govinda Sakhare

11

很有可能不会出现冲突(除非您在高负载系统中,在这种情况下,冲突的可能性非常高),但仍然有可能。

Java已经有了生成唯一标识符的机制 - java.util.UUID。 它有方法可以生成随机ID。

我强烈建议使用它来代替。


就失败概率而言,我怀疑毫秒级方法是否能通过单元测试。 - Dolph
@Dolph - 或者系统负载测试。当然,如果你做得正确,它不应该... - Stephen C
1
我非常喜欢UUID,但它相当低效(我是通过痛苦的经历明白了这一点...)。通常的存储方式是使用UUID.toString(),这个方法返回一个36字节长的字符串(通常映射为类似varchar(36)的类型)。数据库索引应该保持在内存中,索引越大,所需的内存就越多,同时索引的速度也会变慢等等。我建议使用一些高低位方案和long类型的id来解决这个问题。 - bestsss
@bestsss:你能稍微解释一下你提出的聚类位方案吗? - Rajat Gupta

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接