Jelajahi Sumber

fix 雪花生成随机降低重复

zoujiajian 1 bulan lalu
induk
melakukan
f429b76bb8

+ 8 - 1
netflix-common/src/main/java/com/cyksj/common/snowflake/Sequence.java

@@ -72,11 +72,14 @@ public final class Sequence {
                * 用mask防止溢出:位与运算保证计算的结果范围始终是 0-4095
      **/
     private final static long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
+    private final static long RANDOM_SUFFIX_BOUND = 100000L;
+    private final static long RANDOM_SUFFIX_STEP = 23L;
 
     private final long workerId;
     private final long dataCenterId;
     private long sequence = 0L;
     private long lastTimestamp = -1L;
+    private long randomSuffixSeed = 0L;
 
     private static byte LAST_IP = 0;
     private final boolean clock;
@@ -158,10 +161,12 @@ public final class Sequence {
             sequence = tempSequence & SEQUENCE_MASK;
             if (sequence == 0) {
                 currentTimestamp = this.tilNextMillis(lastTimestamp);
+                randomSuffixSeed = tlr.nextLong(RANDOM_SUFFIX_BOUND);
             }
         } else {
             // randomSequence为true表示随机生成允许范围内的序列起始值,否则毫秒内起始值为0L开始自增
             sequence = randomSequence ? tlr.nextLong(SEQUENCE_MASK + 1) : 0L;
+            randomSuffixSeed = tlr.nextLong(RANDOM_SUFFIX_BOUND);
         }
 
         lastTimestamp = currentTimestamp;
@@ -172,13 +177,15 @@ public final class Sequence {
          * 2.然后对每个左移后的值(la、lb、lc、sequence)做位或运算,是为了把各个短的数据合并起来,合并成一个二进制数
          * 3.最后转换成10进制,就是最终生成的id
          */
-        return (currentOffsetTime << TIMESTAMP_LEFT_SHIFT) |
+        long id = (currentOffsetTime << TIMESTAMP_LEFT_SHIFT) |
                 // 数据中心位
                 (dataCenterId << DATA_CENTER_ID_SHIFT) |
                 // 工作ID位
                 (workerId << WORKER_ID_SHIFT) |
                 // 毫秒序列化位
                 sequence;
+        long randomSuffix = (randomSuffixSeed + sequence * RANDOM_SUFFIX_STEP) % RANDOM_SUFFIX_BOUND;
+        return id / RANDOM_SUFFIX_BOUND * RANDOM_SUFFIX_BOUND + randomSuffix;
     }
 
     /**