瀏覽代碼

优化ID生成策略

zhouhao 2 年之前
父節點
當前提交
90f9287097
共有 1 個文件被更改,包括 57 次插入4 次删除
  1. 57 4
      hsweb-core/src/main/java/org/hswebframework/web/id/RandomIdGenerator.java

+ 57 - 4
hsweb-core/src/main/java/org/hswebframework/web/id/RandomIdGenerator.java

@@ -1,12 +1,22 @@
 package org.hswebframework.web.id;
 
 import io.netty.util.concurrent.FastThreadLocal;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
 
 import java.util.Base64;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.concurrent.ThreadLocalRandom;
 
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
 public class RandomIdGenerator {
 
+    // java -Dgenerator.random.instance-id=8
+    private static final RandomIdGenerator GLOBAL = new RandomIdGenerator(
+            Integer.getInteger("generator.random.instance-id", ThreadLocalRandom.current().nextInt()).byteValue()
+    );
+
     private final static FastThreadLocal<byte[]> HOLDER = new FastThreadLocal<byte[]>() {
         @Override
         protected byte[] initialValue() {
@@ -14,16 +24,59 @@ public class RandomIdGenerator {
         }
     };
 
+    private final byte instanceId;
+
+    public static RandomIdGenerator create(byte instanceId) {
+        return new RandomIdGenerator(instanceId);
+    }
 
     public static String random() {
-        return random(HOLDER.get());
+        return GLOBAL.generate();
+    }
+
+    public String generate() {
+        long now = System.currentTimeMillis();
+        byte[] value = HOLDER.get();
+        value[0] = instanceId;
+
+        value[1] = (byte) (now >>> 32);
+        value[2] = (byte) (now >>> 24);
+        value[3] = (byte) (now >>> 16);
+        value[4] = (byte) (now >>> 8);
+        value[5] = (byte) (now);
+
+        nextBytes(value, 6, 8);
+        nextBytes(value, 9, 15);
+        nextBytes(value, 16, 24);
+
+        return Base64.getUrlEncoder().encodeToString(value);
     }
 
-    public static String random(byte[] container) {
 
-        ThreadLocalRandom.current().nextBytes(container);
+    private static void nextBytes(byte[] bytes, int offset, int len) {
+        ThreadLocalRandom random = ThreadLocalRandom.current();
+
+        for (int i = offset; i < len; ) {
+            for (int rnd = random.nextInt(),
+                 n = Math.min(len - i, Integer.SIZE / Byte.SIZE);
+                 n-- > 0; rnd >>= Byte.SIZE) {
+                bytes[i++] = (byte) rnd;
+            }
+        }
 
-        return Base64.getUrlEncoder().encodeToString(container);
     }
 
+
+    public static void main(String[] args) {
+        System.out.println(random());
+        System.out.println(random().length());
+        Set<String> distinct = new HashSet<>(100_0000);
+
+        long time = System.currentTimeMillis();
+        for (int i = 0; i < 100_0000; i++) {
+            distinct.add(random());
+        }
+        System.out.println(distinct.size());
+        System.out.println(System.currentTimeMillis() - time);
+    }
 }