java8的uuid生成方式比较方便,但是速度不够快
UUID.randomUUID().toString()
我在自己电脑虚拟机上进行测试4core,8G,2.5GHZ
虚拟机,开4个线程,每个线程创建100万个uuid,那么4个线程全部完成,统计速度仅有10w+ ops/sec
为什么要更快的生成速度?
最近要给流计算场景中的事件添加分布式唯一编码,如果生成uuid速度太慢,会成为吞吐的瓶颈
uuid实际上是有标准的,具体实现方法也有很多,格式也有很多种,那么我这里跟jdk的uuid格式保持一致
8-4-4-4-12一共36位,每一位是16进制字符
分布式唯一
mac地址+ 时间信息
UUID生成器获取本机的mac地址信息,那么运行在同一台设备上的生成器使用相同的mac地址信息
时间信息则由下面的方式获取
public static long createTime(final long currentTimeMillis) {
final long timeMillis = currentTimeMillis * 10000L + 122192928000000000L;
final long currNewLastTime = atomicLastTime.get();
if (timeMillis > currNewLastTime) {
atomicLastTime.compareAndSet(currNewLastTime, timeMillis);
}
return atomicLastTime.incrementAndGet();
}
UUID生成办法
public Appendable toAppendable(final Appendable a) {
Appendable out = a;
if (out == null) {
out = new StringBuilder(36);
}
try {
Hex.append(out, (int) (this.time >> 32)).append('-');
Hex.append(out, (short) (this.time >> 16)).append('-');
Hex.append(out, (short) this.time).append('-');
Hex.append(out, (short) (this.clockSeqAndNode >> 48)).append('-');
Hex.append(out, this.clockSeqAndNode, 12);
} catch (IOException ex) {
}
return out;
}
时间信息是个long类型,64位,取高32位作为int类型数字作为UUID的第一个8位,取低32位的前后16位分别作为short类型充当UUID后面的2个4位,这时候剩下的一个4位和12位则是跟mac地址有关
clockSeqAndNode |= Hex.parseLong(macAddress)
clockSeqAndNode同样是long类型,那么取高16位作剩下一个4位,最后的12位则通过跳步得到
public static Appendable append(final Appendable a, final long in, final int length) {
try {
for (int lim = (length << 2) - 4; lim >= 0; lim -= 4) {
a.append(DIGITS[(byte) (in >> lim) & 0xF]);
}
} catch (IOException ex) {
}
return a;
}
那么根据上面的原理,我们知道同一个设备上面生成的uuid有几个特点,后面的4+12 = 16位是一致的,不变的
前面的8+4+4里面第一个8位短时间内也是不变的,后面2个4位是不同的,并且连续生成的话,数值也是连续的
01e9e106-eee1-f5b0-b4cc-02426648b365
01e9e106-eee1-f5b1-b4cc-02426648b365
01e9e106-eee1-f5b2-b4cc-02426648b365
01e9e106-eee1-f5b3-b4cc-02426648b365
01e9e106-eee1-f5b4-b4cc-02426648b365
01e9e106-eee1-f5b5-b4cc-02426648b365
01e9e106-eee1-f5b6-b4cc-02426648b365
01e9e106-eee1-f5b7-b4cc-02426648b365
01e9e106-eee1-f5b8-b4cc-02426648b365
01e9e106-eee1-f5b9-b4cc-02426648b365
性能
同样的测试办法,生成速度大概230w+ ops/sec,是jdk8 uuid速度的20多倍,完全可以满足我的需求了。