【问题标题】:Sequential Guid in JavaJava中的顺序指南
【发布时间】:2011-01-13 04:19:14
【问题描述】:

考虑到我发表的关于 Microsoft.NET 框架上的顺序 guid 性能的帖子(请参阅What are the performance improvement of Sequential Guid over standard Guid?),是否有人对在 Windows DLL 中实现的相同算法进行了正确、可靠、快速且运行良好的 Java 实现?

问候 马西莫

【问题讨论】:

    标签: java guid sequential


    【解决方案1】:

    我使用它为我的 DTO 生成 UUID(通用唯一 ID),它们充当临时集合的代理键。不知道是不是一样,但它可能会为您指明正确的方向。

    import java.util.UUID;
    ...
        private String uuid=null;
    ...
        protected String getUuid() {
            synchronized (this) {
              if (null ==uuid) {
                uuid = UUID.randomUUID().toString();
              }
              return uuid;
            }
          }
    

    【讨论】:

    • 不,这会创建一个标准随机 Guid,我需要一个顺序 guid。
    【解决方案2】:

    请参阅这篇文章:http://www.informit.com/articles/article.aspx?p=25862&seqNum=7(链接到第 7 页)。

    它包含一个算法,作者称之为“COMB”Guids;我在下面重现了他的代码(SQL):

    SET @aGuid = CAST(CAST(NEWID() AS BINARY(10)) 
    + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
    

    将其转换为 Java 或您想要的语言很简单。显而易见的基本原则是使日期成为 Guid 的组成部分。整篇文章读起来很不错,因为他对各种方法的性能做了很好的分析。

    【讨论】:

      【解决方案3】:

      此页面链接到 Java 中的几个版本 1(顺序)UUID 实现: http://johannburkard.de/blog/programming/java/Java-UUID-generators-compared.html

      【讨论】:

        【解决方案4】:

        对于顺序 UUID,您正在寻找版本 1 UUID。 Java UUID Generator 项目似乎运行良好并且非常易于使用:

        Generators.timeBasedGenerator().generate().toString()
        

        【讨论】:

        • 链接似乎已损坏。一些搜索表明这可能是这里讨论的项目:github.com/cowtowncoder/java-uuid-generator
        • 谢谢。乍一看,生成的 uuid 似乎是连续的。也许我对页面拆分的战争还没有丢失..
        【解决方案5】:

        生成 COMB UUID 的实用程序类,由 Jimmy Nilsson 在本文中构思:http://www.informit.com/articles/article.aspx?p=25862。随意使用和分享。

        package your.package.name;
        
        import java.security.SecureRandom;
        import java.util.Random;
        import java.util.UUID;
        
        /**
         * Utility class that creates COMB UUIDs.
         * 
         * The COMB UUIDs combine the creation time and random bytes.
         * 
         * The PREFIX or SUFFIX has 6 bytes and corresponds to the milliseconds since
         * 1970-01-01T00:00:00Z (Unix epoch).
         * 
         * For RFC-4122 compliance, it uses the version number 4.
         * 
         * Read: The Cost of GUIDs as Primary Keys
         * http://www.informit.com/articles/article.aspx?p=25862
         * 
         */
        public abstract class CombUuidCreator {
        
            private static final int RANDOM_VERSION = 4;
        
            /**
             * Returns a prefix COMB UUID.
             * 
             * It uses a thread local {@link SecureRandom}.
             * 
             * @return a random-based UUID
             */
            public static UUID getPrefixComb() {
                return getPrefixComb(SecureRandomLazyHolder.THREAD_LOCAL_RANDOM.get());
            }
        
            /**
             * Returns a prefix COMB UUID.
             * 
             * It uses any instance of {@link Random}.
             * 
             * @return a random-based UUID
             */
            public static UUID getPrefixComb(Random random) {
                return getCombGuid(random, /* prefix = */true);
            }
        
            /**
             * Returns a suffix COMB UUID.
             * 
             * It uses a thread local {@link SecureRandom}.
             * 
             * @return a random-based UUID
             */
            public static UUID getSuffixComb() {
                return getSuffixComb(SecureRandomLazyHolder.THREAD_LOCAL_RANDOM.get());
            }
        
            /**
             * Returns a suffix COMB UUID.
             * 
             * It uses any instance of {@link Random}.
             * 
             * @return a random-based UUID
             */
            public static UUID getSuffixComb(Random random) {
                return getCombGuid(random, /* prefix = */false);
            }
        
            /**
             * Returns prefix or suffix COMB UUID.
             * 
             * It uses any instance of {@link Random}.
             * 
             * @return a random-based UUID
             */
            private static UUID getCombGuid(Random random, boolean prefix) {
        
                long msb = 0;
                long lsb = 0;
        
                // (3) set bits randomly
                final byte[] bytes = new byte[16];
                random.nextBytes(bytes);
                final long rand0 = (bytes[8] << 8) | (bytes[9] & 0xff);
                final long rand1 = toNumber(bytes, 0, 8);
        
                // Insert the prefix in the MSB
                final long timestamp = System.currentTimeMillis();
                if (prefix) {
                    msb = (rand0 & 0x000000000000ffffL) | ((timestamp & 0x0000ffffffffffffL) << 16);
                    lsb = rand1;
                } else {
                    msb = rand1;
                    lsb = (rand0 << 48) | (timestamp & 0x0000ffffffffffffL);
                }
        
                // Apply version and variant bits (required for RFC-4122 compliance)
                msb = (msb & 0xffffffffffff0fffL) | (RANDOM_VERSION & 0x0f) << 12; // apply version bits
                lsb = (lsb & 0x3fffffffffffffffL) | 0x8000000000000000L; // apply variant bits
        
                // Return the UUID
                return new UUID(msb, lsb);
            }
        
            private static long toNumber(final byte[] bytes, final int start, final int length) {
                long result = 0;
                for (int i = start; i < length; i++) {
                    result = (result << 8) | (bytes[i] & 0xff);
                }
                return result;
            }
        
            // Holds thread local secure random
            private static class SecureRandomLazyHolder {
                static final ThreadLocal<Random> THREAD_LOCAL_RANDOM = ThreadLocal.withInitial(SecureRandom::new);
            }
        
            /**
             * For tests!
             */
            public static void main(String[] args) {
        
                Random random = new Random();
        
                System.out.println("// Prefix COMB using thread local `java.security.SecureRandom` (DEFAULT)");
                System.out.println("CombUuidCreator.getPrefixComb()");
                System.out.println();
                for (int i = 0; i < 5; i++) {
                    System.out.println(" " + CombUuidCreator.getPrefixComb());
                }
                System.out.println("|----prefix---|----------------------|");
        
                System.out.println();
                System.out.println("// Prefix COMB using `java.util.Random` (FASTER)");
                System.out.println("CombUuidCreator.getPrefixComb(new Random())");
                System.out.println();
                for (int i = 0; i < 5; i++) {
                    System.out.println(" " + CombUuidCreator.getPrefixComb(random));
                }
                System.out.println("|----prefix---|----------------------|");
        
                System.out.println();
                System.out.println("// Suffix COMB using thread local `java.security.SecureRandom` (DEFAULT)");
                System.out.println("CombUuidCreator.getSuffixComb()");
                System.out.println();
                for (int i = 0; i < 5; i++) {
                    System.out.println(" " + CombUuidCreator.getSuffixComb());
                }
                System.out.println("|-----------------------|---suffix---|");
        
                System.out.println();
                System.out.println("// Suffix COMB using `java.util.Random` (FASTER)");
                System.out.println("CombUuidCreator.getSuffixComb(new Random())");
                System.out.println();
                for (int i = 0; i < 5; i++) {
                    System.out.println(" " + CombUuidCreator.getSuffixComb(random));
                }
                System.out.println("|-----------------------|---suffix---|");
            }
        }
        

        这是输出:

        // Prefix COMB using thread local `java.security.SecureRandom` (DEFAULT)
        CombUuidCreator.getPrefixComb()
        
         0173861f-4445-459b-87d2-39a970520fff
         0173861f-4445-465d-a216-7b13d86c83a1
         0173861f-4445-4c67-b75e-3845c2911420
        |----prefix---|----------------------|
        
        // Prefix COMB using `java.util.Random` (FASTER)
        CombUuidCreator.getPrefixComb(new Random())
        
         0173861f-4445-44f6-bfa4-e272c9c369aa
         0173861f-4445-446e-baf2-6db6ab808094
         0173861f-4445-40e8-a452-184dcf9736fd
        |----prefix---|----------------------|
        
        // Suffix COMB using thread local `java.security.SecureRandom` (DEFAULT)
        CombUuidCreator.getSuffixComb()
        
         726b6717-001a-4317-9a9b-0173861f4446
         dfdce2d2-7517-4a3f-9f3d-0173861f4446
         a7fd6236-8065-4395-b49a-0173861f4446
        |-----------------------|---suffix---|
        
        // Suffix COMB using `java.util.Random` (FASTER)
        CombUuidCreator.getSuffixComb(new Random())
        
         41a6a4cd-eb4c-410f-8eb2-0173861f4446
         7c0a315e-54de-476a-a2a8-0173861f4446
         4e9ddf9e-ac07-4cf3-bf3f-0173861f4446
        |-----------------------|---suffix---|
        

        您还可以使用uuid-creator 库。请参阅以下示例:

        // Create a prefix COMB UUID
        UUID uuid = UuidCreator.getPrefixComb();
        
        // Create a suffix COMB UUID
        UUID uuid = UuidCreator.getSuffixComb();
        

        项目页面:https://github.com/f4b6a3/uuid-creator

        【讨论】:

          猜你喜欢
          • 2023-04-06
          • 2013-11-18
          • 2019-01-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-02
          • 1970-01-01
          相关资源
          最近更新 更多