简介

  • 生成随机数,一般来说用的不是很多,会用一些第三方的工具包来生成分布式ID

    源码

    1. public final class UUID implements java.io.Serializable, Comparable<UUID> {
    2. private static final long serialVersionUID = -4856846361193249489L;
    3. // uuid 的最高有效位为64位
    4. private final long mostSigBits;
    5. // uuid 的最低有效位为64位
    6. private final long leastSigBits;
    7. // 此类使用的随机数生成器来创建基于随机的UUID。
    8. private static class Holder {
    9. static final SecureRandom numberGenerator = new SecureRandom();
    10. }
    11. // 私有构造函数,它使用字节数组构造新的UUID。
    12. private UUID(byte[] data) {
    13. long msb = 0;
    14. long lsb = 0;
    15. // 断言长度为16位
    16. assert data.length == 16 : "data must be 16 bytes in length";
    17. for (int i=0; i<8; i++)
    18. msb = (msb << 8) | (data[i] & 0xff);
    19. for (int i=8; i<16; i++)
    20. lsb = (lsb << 8) | (data[i] & 0xff);
    21. this.mostSigBits = msb;
    22. this.leastSigBits = lsb;
    23. }
    24. // 有参构造
    25. public UUID(long mostSigBits, long leastSigBits) {
    26. this.mostSigBits = mostSigBits;
    27. this.leastSigBits = leastSigBits;
    28. }
    29. // 静态方法 使用最多的方法
    30. public static UUID randomUUID() {
    31. // 使用SecureRandom生成随机数,替换version和variant就是 UUID
    32. SecureRandom ng = Holder.numberGenerator;
    33. byte[] randomBytes = new byte[16];
    34. ng.nextBytes(randomBytes);
    35. randomBytes[6] &= 0x0f; /* clear version */
    36. randomBytes[6] |= 0x40; /* set to version 4 */
    37. randomBytes[8] &= 0x3f; /* clear variant */
    38. randomBytes[8] |= 0x80; /* set to IETF variant */
    39. return new UUID(randomBytes);
    40. }
    41. // 静态工厂检索类型3(基于名称的) UUID的基于指定的字节数组
    42. public static UUID nameUUIDFromBytes(byte[] name) {
    43. MessageDigest md;
    44. try {
    45. md = MessageDigest.getInstance("MD5");
    46. } catch (NoSuchAlgorithmException nsae) {
    47. throw new InternalError("MD5 not supported", nsae);
    48. }
    49. byte[] md5Bytes = md.digest(name);
    50. md5Bytes[6] &= 0x0f; /* clear version */
    51. md5Bytes[6] |= 0x30; /* set to version 3 */
    52. md5Bytes[8] &= 0x3f; /* clear variant */
    53. md5Bytes[8] |= 0x80; /* set to IETF variant */
    54. return new UUID(md5Bytes);
    55. }
    56. // 创建一个UUID如在所描述的字符串标准表示toStrin
    57. public static UUID fromString(String name) {
    58. String[] components = name.split("-");
    59. if (components.length != 5)
    60. throw new IllegalArgumentException("Invalid UUID string: "+name);
    61. for (int i=0; i<5; i++)
    62. components[i] = "0x"+components[i];
    63. long mostSigBits = Long.decode(components[0]).longValue();
    64. mostSigBits <<= 16;
    65. mostSigBits |= Long.decode(components[1]).longValue();
    66. mostSigBits <<= 16;
    67. mostSigBits |= Long.decode(components[2]).longValue();
    68. long leastSigBits = Long.decode(components[3]).longValue();
    69. leastSigBits <<= 48;
    70. leastSigBits |= Long.decode(components[4]).longValue();
    71. return new UUID(mostSigBits, leastSigBits);
    72. }
    73. // 获取低位个数
    74. public long getLeastSignificantBits() {
    75. return leastSigBits;
    76. }
    77. // 获取最长的个数
    78. public long getMostSignificantBits() {
    79. return mostSigBits;
    80. }
    81. // 获得版本号
    82. // 与此相关联的版本号UUID 。 版本号描述这怎么UUID生成。 版本号具有以下含义:
    83. // 基于时间的UUID 1
    84. // 2 DCE安全UUID
    85. // 基于名字的3 UUID
    86. // 4随机生成UUID
    87. public int version() {
    88. // Version is bits masked by 0x000000000000F000 in MS long
    89. return (int)((mostSigBits >> 12) & 0x0f);
    90. }
    91. public int variant() {
    92. // This field is composed of a varying number of bits.
    93. // 0 - - Reserved for NCS backward compatibility
    94. // 1 0 - The IETF aka Leach-Salz variant (used by this class)
    95. // 1 1 0 Reserved, Microsoft backward compatibility
    96. // 1 1 1 Reserved for future definition.
    97. return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62)))
    98. & (leastSigBits >> 63));
    99. }
    100. // 生成时间戳
    101. public long timestamp() {
    102. if (version() != 1) {
    103. throw new UnsupportedOperationException("Not a time-based UUID");
    104. }
    105. return (mostSigBits & 0x0FFFL) << 48
    106. | ((mostSigBits >> 16) & 0x0FFFFL) << 32
    107. | mostSigBits >>> 32;
    108. }
    109. // 与此UUID相关联的时钟序列值
    110. public int clockSequence() {
    111. if (version() != 1) {
    112. throw new UnsupportedOperationException("Not a time-based UUID");
    113. }
    114. return (int)((leastSigBits & 0x3FFF000000000000L) >>> 48);
    115. }
    116. // 与此UUID相关联的节点的值
    117. public long node() {
    118. if (version() != 1) {
    119. throw new UnsupportedOperationException("Not a time-based UUID");
    120. }
    121. return leastSigBits & 0x0000FFFFFFFFFFFFL;
    122. }
    123. // toString方法
    124. public String toString() {
    125. return (digits(mostSigBits >> 32, 8) + "-" +
    126. digits(mostSigBits >> 16, 4) + "-" +
    127. digits(mostSigBits, 4) + "-" +
    128. digits(leastSigBits >> 48, 4) + "-" +
    129. digits(leastSigBits, 12));
    130. }
    131. // 返回VAL由十六进制数字指定的数来表示。
    132. private static String digits(long val, int digits) {
    133. long hi = 1L << (digits * 4);
    134. return Long.toHexString(hi | (val & (hi - 1))).substring(1);
    135. }
    136. public int hashCode() {
    137. long hilo = mostSigBits ^ leastSigBits;
    138. return ((int)(hilo >> 32)) ^ (int) hilo;
    139. }
    140. public boolean equals(Object obj) {
    141. if ((null == obj) || (obj.getClass() != UUID.class))
    142. return false;
    143. UUID id = (UUID)obj;
    144. return (mostSigBits == id.mostSigBits &&
    145. leastSigBits == id.leastSigBits);
    146. }
    147. public int compareTo(UUID val) {
    148. return (this.mostSigBits < val.mostSigBits ? -1 :
    149. (this.mostSigBits > val.mostSigBits ? 1 :
    150. (this.leastSigBits < val.leastSigBits ? -1 :
    151. (this.leastSigBits > val.leastSigBits ? 1 :
    152. 0))));
    153. }
    154. }

    总结

  • UUID 是指Universally Unique Identifier,翻译为中文是通用唯一识别码,UUID 的目的是让分布式系统中的所有元素都能有唯一的识别信息。如此一来,每个人都可以创建不与其它人冲突的 UUID,就不需考虑数据库创建时的名称重复问题。

  • 123e4567-e89b-12d3-a456-426655440000
  • xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
  • 数字 M的四位表示 UUID 版本,当前规范有5个版本,M可选值为1, 2, 3, 4, 5 ;
  • 数字 N的一至四个最高有效位表示 UUID 变体( variant ),有固定的两位10xx因此只可能取值8, 9, a, b
  • UUID版本通过M表示,当前规范有5个版本,M可选值为1, 2, 3, 4, 5。这5个版本使用不同算法,利用不同的信息来产生UUID,各版本有各自优势,适用于不同情景。具体使用的信息
  • version 1, date-time & MAC address
    • version 2, date-time & group/user id
  • version 3, MD5 hash & namespace

    • version 4, pseudo-random number
    • version 5, SHA-1 hash & namespace

      Mark*

  • 在学习分布式ID生成的时候,会更加详细的讲解UUID