分布式标识 Distributed ID-02-UUID
2018年9月5日大约 5 分钟
UUID
基本实现
@Override
public String genId() {
return UUID.randomUUID().toString()
.replaceAll(PunctuationConst.MIDDLE_LINE, PunctuationConst.EMPTY);
}
测试代码
System.out.println(new UUIDId().genId())
日志信息
379a1e5df3534885a94001373467f33e
源码解析
toString()
public String toString() {
return (digits(mostSigBits >> 32, 8) + "-" +
digits(mostSigBits >> 16, 4) + "-" +
digits(mostSigBits, 4) + "-" +
digits(leastSigBits >> 48, 4) + "-" +
digits(leastSigBits, 12));
}
digits()
private static String digits(long val, int digits) {
long hi = 1L >>= shift;
} while (i != 0);
return new String(buf, charPos, (64 - charPos));
}
其中 Integer.digits 是最基本的常量
/**
* All possible chars for representing a number as a String
*/
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};
random()
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);
}
SecureRandom 单例初始化
其中 Holder.numberGenerator 创建单例 SecureRandom
private static class Holder {
static final SecureRandom numberGenerator = new SecureRandom();
}
UUID(bytes)
构造器,内容如下
private UUID(byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i=0; i uuidUnits = uuidUnits();
StringBuilder stringBuilder = new StringBuilder();
for (String unit : uuidUnits) {
int x = Integer.parseInt(unit, 16);
stringBuilder.append(CHARS[x % 62]);
}
return stringBuilder.toString();
}
/**
* 获取 uuid 分段后的内容
* @return 分段后的内容
*/
private List uuidUnits() {
final String uuid32 = new UUID32().genId();
final int size = 8;
List units = Guavas.newArrayList(size);
for(int i = 0; i
/// Generate a new using the comb algorithm.
///
private Guid GenerateComb()
{
byte[] guidArray = Guid.NewGuid().ToByteArray();
DateTime baseDate = new DateTime(1900, 1, 1);
DateTime now = DateTime.Now;
// Get the days and milliseconds which will be used to build
//the byte string
TimeSpan days = new TimeSpan(now.Ticks - baseDate.Ticks);
TimeSpan msecs = now.TimeOfDay;
// Convert to a byte array
// Note that SQL Server is accurate to 1/300th of a
// millisecond so we divide by 3.333333
byte[] daysArray = BitConverter.GetBytes(days.Days);
byte[] msecsArray = BitConverter.GetBytes((long)
(msecs.TotalMilliseconds / 3.333333));
// Reverse the bytes to match SQL Servers ordering
Array.Reverse(daysArray);
Array.Reverse(msecsArray);
// Copy the bytes into the guid
Array.Copy(daysArray, daysArray.Length - 2, guidArray,
guidArray.Length - 6, 2);
Array.Copy(msecsArray, msecsArray.Length - 4, guidArray,
guidArray.Length - 4, 4);
return new Guid(guidArray);
}
个人收获
uuid
uuid 从实现上看起来很简单,一个方法即可。
但是其中的原理是一样的。
组合
组合是一种非常好的方式。
其实后面的随机序列也是一种组合。
时间戳+随机数的组合
前者保证顺序性,后者保证唯一性。
贡献者
binbin.hou