学习借鉴hibernate的UUID的使用方式

以下是百度百科上经“科普中国”审核的资料
定义
UUID是由一组32位数的16进制数字所构成,是故UUID理论上的总数为1632=2128,约等于3.4 x 10^38。也就是说若每纳秒产生1兆个UUID,要花100亿年才会将所有UUID用完。
UUID的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的32个字符。示例:
550e8400-e29b-41d4-a716-446655440000
UUID亦可刻意重复以表示同类。例如说微软的COM中,所有组件皆必须实现出IUnknown接口,方法是产生一个代表IUnknown的UUID。无论是程序试图访问组件中的IUnknown接口,或是实现IUnknown接口的组件,只要IUnknown一被使用,皆会被参考至同一个ID:00000000-0000-0000-C000-000000000046。 [1]
组成
UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成的API。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和随机数。
UUID由以下几部分的组合:
(1)当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
(2)时钟序列。
(3)全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
UUID的唯一缺陷在于生成的结果串会比较长。关于UUID这个标准使用最普遍的是微软的GUID(Globals Unique Identifiers)。在ColdFusion中可以用CreateUUID()函数很简单地生成UUID,其格式为:xxxxxxxx-xxxx- xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字。而标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12),可以从cflib 下载CreateGUID() UDF进行转换。 [2]

在网上找了很多资料后,还是对UUID一知半解,最终决看hibernate的源码,来解惑。经过长达一个小时的断点调试后,终于找了UUID的包位置:

package org.hibernate.id.UUIDHexGenerator

本类最核心的是下面这个方法:

   public Serializable generate(SessionImplementor session, Object obj) {
    return (new StringBuffer(36)).append(this.format(this.getIP())).append(this.sep).append(this.format(this.getJVM())).append(this.sep).append(this.format(this.getHiTime())).append(this.sep).append(this.format(this.getLoTime())).append(this.sep).append(this.format(this.getCount())).toString();
}
  • 这个方法的作用就是形成8-8-4-8-4共32位的UUID字符编码,也就是最终的UUID

  • 从这里可以发现,按照百科的说法
    1.关于UUID这个标准使用最普遍的是微软的GUID 格式是8-4-4-16
    2.标准的UUID格式为 8-4-4-4-12

  • 从上面几点我推测UUID的编码格式并不固定,只有唯一性才是其重要的地方。

那么,hibernate是按照什么规则来生成这个UUID的呢?

  1. IP地址8位
  2. JVM启动时的时间编码八位
  3. 当前时间右移32位后的编码4位(按照此刻毫秒,右移32位是363,然后363编码成4位)
  4. 当前时间编码八位
  5. 累计编码数四位

以下是编码方式

protected String format(int intValue) {
    String formatted = Integer.toHexString(intValue);
    StringBuffer buf = new StringBuffer("00000000");
    buf.replace(8 - formatted.length(), 8, formatted);
    return buf.toString();
}

protected short getCount() {
    Class var1 = AbstractUUIDGenerator.class;
    synchronized(AbstractUUIDGenerator.class) {
        if (counter < 0) {
            counter = 0;
        }
        return counter++;
    }
}

以上五种方式组成的编码,具有全球唯一性。

  • 首先第一点IP本身就是唯一的,这就做到每台服务器都有自己的一套UUID,而不会重复
  • 第二点,JVM的启动时间,考虑到一台服务器可能运行多个程序,这样同一服务器上的不同服务又各不冲突(基本上排除两个Java程序完全在同一毫秒启动这种恶性到不可能的事件)
  • 第三点和第四点又确定了在不同时间(精确到毫秒)生成的UUID各不相同
  • 最后一点,因为计算机性能的显著提升,以我的计算机为例,1毫秒可以生成五十多个UUID,所以还需要用累计编码的方式区分同一毫秒下生成的UUID

UUID很好用,但是也确实占用资源,毕竟32位的数据还是很庞大的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值