• 【Mybatis工具(四)】UUID实现原理及其Java实现


    UUID(Universally Unique Identifier),翻译为中文是通用唯一识别码,UUID 的目的是让分布式系统中的所有元素都能有唯一的识别信息。如此一来,每个人都可以创建不与其它人冲突的 UUID,就不需考虑数据库创建时的名称重复问题。UUID 是由一组32位数的16进制数字所构成,是故 UUID 理论上的总数为1632=2128,约等于3.4 x 10123。也就是说若每纳秒产生1百万个 UUID,要花100亿年才会将所有 UUID 用完。

    格式

    UUID 的128bit数字被表示为32个十六进制数字,以连字号分隔的五组来显示,形式为8-4-4-4-12,总共有 36个字符(即三十二个英数字母和四个连字号)。例如:
    123e4567-e89b-12d3-a456-426655440000

    xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
    到目前为止业界一共有5种方式生成UUID,这5种方式使用不同算法,利用不同的信息来产生UUID,各版本有各自优势,适用于不同情景。其中,数字M的4bit数字表示 UUID 版本,可选值为1, 2, 3, 4, 5对应当前规范的5个版本。

    为了能兼容过去的UUID,以及应对未来的变化,因此有了变体(Variants)这一概念。目前已知的变体有如下几种:(其中字母“x”表示一个“不关心”值)
    variant 0:0xxx。为了向后兼容预留。
    variant 1:10xx。当前正在使用的。
    variant 2:110x。为早期微软GUID预留。
    variant 3:111x。为将来扩展预留。目前暂未使用。

    其中,数字N的的4bit数字表示 UUID 变体( variant ),根据规定目前使用的variant有固定的两位10xx,因此只可能取值8, 9, a, b

    有关UUID格式,详情见IETF发布的UUID规范 A Universally Unique IDentifier (UUID) URN Namespace

    版本介绍

    • version 1, date-time & MAC address

    基于时间戳及MAC地址的UUID实现。它包括了48位的MAC地址和60位的时间戳。

    • version 2, date-time & group/user id

    这是最神秘的版本,RFC没有提供具体的实现细节,以至于大部分的UUID库都没有实现它,只在特定的场景(DCE security)才会用到。所以绝大数情况,我们也不会碰到它。

    • version 3, MD5 hash & namespace
    • version 5, SHA-1 hash & namespace

    V3和V5都是通过hash namespace的标识符和名称生成的。V3使用MD5作为hash函数,V5则使用SHA-1。

     /**
         * Static factory to retrieve a type 3 (name based) {@code UUID} based on
         * the specified byte array.
         *
         * @param  name
         *         A byte array to be used to construct a {@code UUID}
         *
         * @return  A {@code UUID} generated from the specified array
         */
        public static UUID nameUUIDFromBytes(byte[] name) {
            MessageDigest md;
            try {
                md = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException nsae) {
                throw new InternalError("MD5 not supported", nsae);
            }
            byte[] md5Bytes = md.digest(name);
            md5Bytes[6]  &= 0x0f;  /* clear version        */
            md5Bytes[6]  |= 0x30;  /* set to version 3     */
            md5Bytes[8]  &= 0x3f;  /* clear variant        */
            md5Bytes[8]  |= 0x80;  /* set to IETF variant  */
            return new UUID(md5Bytes);
        }
    
    • version 4, pseudo-random number

    这个版本使用最为广泛,其中4位代表版本,2-3位代表variant。余下的122-121位都是全部随机的。即有2的122次方(5.3后面36个0)个UUID。一个标准实现的UUID库在生成了2.71万亿个UUID会产生重复UUID的可能性也只有50%的概率。这相当于每秒产生10亿的UUID,持续85年,而把这些UUID都存入文件,每个UUID占16bytes,总需要45 EB(exabytes),比目前最大的数据库(PB)还要大很多倍。

    /**
         * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
         *
         * The {@code UUID} is generated using a cryptographically strong pseudo
         * random number generator.
         *
         * @return  A randomly generated {@code UUID}
         */
        public static UUID randomUUID() {
            SecureRandom ng = Holder.numberGenerator;
    
            byte[] randomBytes = new byte[16];
            ng.nextBytes(randomBytes);
            randomBytes[6]  &= 0x0f;  /* clear version        */
            randomBytes[6]  |= 0x40;  /* set to version 4     */
            randomBytes[8]  &= 0x3f;  /* clear variant        */
            randomBytes[8]  |= 0x80;  /* set to IETF variant  */
            return new UUID(randomBytes);
        }
    

    如何使用UUID

    Java的JDK1.8是支持UUID生成的,使用下面的语法,即可生成一个版本4的UUID。

    System.out.println(UUID.randomUUID().toString());
    

    参考文献

    为什么不能用uuid做MySQL的主键

  • 相关阅读:
    JQ 选择器大全
    .NET SOCKET通信编程
    .Net中的Socket通讯
    SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪
    C# 编写Window服务基础(一)
    更改windows服务的配置文件app.config
    SQLServer数据库表中将指定列分组转一行
    在c#中使用mongo-csharp-driver操作mongodb
    java 线程池的原理
    Java并发编程:ThreadLocal的使用以及实现原理解析
  • 原文地址:https://www.cnblogs.com/zllk/p/13847958.html
Copyright © 2020-2023  润新知