我们有一个6节点的Red Hat 4.4.7/Linux 2.6.32网络,每个节点运行一个Java应用程序,该应用程序使用Hibernate 3.3.2.GA在中央Oracle数据库中创建记录。休眠生成重复的UUID
我们遇到了Hibernate生成重复UUID的问题。问题
的Java类的定义如下:
@Entity
@Table(name = "X_Y")
@GenericGenerator(name = "x-y-uuid", strategy = "uuid")
public class XY implements ... {
@Id
@Column(name = "X_Y_ID")
@GeneratedValue(generator = "x-y-uuid")
private String id;
...
}
根据这个定义,我们已经成功地使用了一段时间,我们遇到了重复X_Y_ID键的问题。我们禁用了X_Y_ID上的唯一约束并重新执行该过程。与此同时,我们开始在我们的代码以及Hibernate代码中寻找可能的错误。读Hibernate的UUIDHexGenerator
它会出现UUID的前8个字符是基于机器IP地址,第二个8个字符是基于JVM启动时间。
在X_Y_ID上禁用唯一约束的过程完成之后,我们对生成的UUID进行了一些分析。我们发现实际上有59个重复的X_Y_ID值。 令我们吃惊的是,查询:
select SUBSTR(X_Y_ID,1,8), COUNT(*)
from X_Y
group by SUBSTR(X_Y_ID,1,8)
表明,所有6台机器具有相同的前8个字符。查询:
select SUBSTR(X_Y_ID,9,8), COUNT(*)
from X_Y
group by SUBSTR(X_Y_ID,9,8)
给
"49d99de6" 2148309
"49d99e3c" 2044966
"49d99def" 2228095
"49d99df2" 2091068
"49d99dee" 4110661
正如你可以看到有5行与行的最后有大约两倍。这本身并不奇怪。 (这一切意味着两台不同机器上的JVM在彼此的256ms内启动)。
稍作进一步调查显示,为前八个字符ff808081
生成的值对应于本地主机127.0.0.1的IP地址。
这些机器上的一个运行ifconfig
给出(作为一个例子):
eth0 Link encap:Ethernet HWaddr 00:50:56:81:2C:20
inet addr:10.191.8.50 Bcast:10.191.63.255 Mask:255.255.192.0
inet6 addr: fe80::250:56ff:fe81:2c20/64 Scope:Link
...
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
...
我的问题是:
- 怎么可能是由Hibernate看到的IP地址为127.0.0.1而不是说10.191.8.50?
- 我们可以做些什么来防止在部署系统上发生这种情况?
这显然是Hibernate中的一个bug,应该修正它们。但是,'grep $ HOSTNAME/etc/hosts'并查看是否有条目'127.0.0.1 yourhostname' – 2014-11-24 17:54:02
@JasonC为什么Hibernate没有生成不通用且不唯一的UUID?如果他们遵循[RFC](http://www.ietf.org/rfc/rfc4122.txt),而不是自行滚动,则不会发生这种情况。 – 2014-11-24 18:10:52
@thatotherguy是的,实际上,更仔细地看待'UUIDHexGenerator',这是一个相当差的实现。我从来没有真正意识到它是如何脱落的......我将重新回答我的答案,以反映这一点。 – 2014-11-24 18:36:51