Skip to content

Commit 7b10b28

Browse files
committed
分布式ID雪花算法优化
1 parent 3b27e29 commit 7b10b28

File tree

2 files changed

+54
-10
lines changed

2 files changed

+54
-10
lines changed

SpringBoot/DistributedID/src/main/java/com/example/snow/IdWorkerPatch.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
* 如果ID生成不频繁,则生成的就是全是偶数
1111
* 改良版雪花算法,解决全为偶数问题,保证低并发时奇偶交替
1212
*
13+
* 时钟回拨问题直接抛出异常,过于简单
14+
* 优化如果时间偏差大小小于5ms,则等待两倍时间重试一次,加强可用性
15+
*
1316
* SnowFlake的结构如下(每部分用-分开):<br>
1417
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
1518
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
@@ -140,9 +143,28 @@ public synchronized long nextId() {
140143

141144
// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
142145
if (timestamp < lastTimestamp) {
143-
logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp);
144-
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
145-
lastTimestamp - timestamp));
146+
long offset = lastTimestamp - timestamp;
147+
if (offset <= 5) {
148+
try {
149+
// 时间偏差大小小于5ms,则等待两倍时间重试一次
150+
wait(offset << 1);
151+
timestamp = timeGen();
152+
if (timestamp < lastTimestamp) {
153+
// 还是小于,抛异常
154+
logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp);
155+
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
156+
lastTimestamp - timestamp));
157+
}
158+
} catch (InterruptedException e) {
159+
logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp);
160+
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
161+
lastTimestamp - timestamp));
162+
}
163+
} else {
164+
logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp);
165+
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
166+
lastTimestamp - timestamp));
167+
}
146168
}
147169

148170
// 如果是同一时间生成的,则进行毫秒内序列
@@ -206,10 +228,10 @@ private long timeGen() {
206228
* @throws Exception
207229
*/
208230
public static void main(String[] args) throws Exception {
209-
IdWorkerPatch idWorkerPatchi = new IdWorkerPatch(15L, 15L, 0L);
231+
IdWorkerPatch idWorkerPatch = new IdWorkerPatch(15L, 15L, 0L);
210232
for (int i = 0; i < 10; i++) {
211233
Thread.sleep(1000L);
212-
logger.info("{}", idWorkerPatchi.nextId());
234+
logger.info("{}", idWorkerPatch.nextId());
213235
}
214236
}
215237

SpringBoot/DistributedID/src/main/java/com/example/snow/generator/IdWorkerUpdate.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
* 如果ID生成不频繁,则生成的就是全是偶数
1212
* 改良版雪花算法,解决全为偶数问题,保证低并发时奇偶交替
1313
*
14+
* 时钟回拨问题直接抛出异常,过于简单
15+
* 优化如果时间偏差大小小于5ms,则等待两倍时间重试一次,加强可用性
16+
*
1417
* SnowFlake的结构如下(每部分用-分开):<br>
1518
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
1619
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
@@ -141,9 +144,28 @@ public synchronized long nextId() {
141144

142145
// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
143146
if (timestamp < lastTimestamp) {
144-
logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp);
145-
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
146-
lastTimestamp - timestamp));
147+
long offset = lastTimestamp - timestamp;
148+
if (offset <= 5) {
149+
try {
150+
// 时间偏差大小小于5ms,则等待两倍时间重试一次
151+
wait(offset << 1);
152+
timestamp = timeGen();
153+
if (timestamp < lastTimestamp) {
154+
// 还是小于,抛异常
155+
logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp);
156+
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
157+
lastTimestamp - timestamp));
158+
}
159+
} catch (InterruptedException e) {
160+
logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp);
161+
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
162+
lastTimestamp - timestamp));
163+
}
164+
} else {
165+
logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp);
166+
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
167+
lastTimestamp - timestamp));
168+
}
147169
}
148170

149171
// 如果是同一时间生成的,则进行毫秒内序列
@@ -207,10 +229,10 @@ private long timeGen() {
207229
* @throws Exception
208230
*/
209231
public static void main(String[] args) throws Exception {
210-
IdWorkerUpdate idWorkerPatchi = new IdWorkerUpdate(0L, 0L, 0L);
232+
IdWorkerUpdate idWorkerPatch = new IdWorkerUpdate(0L, 0L, 0L);
211233
for (int i = 0; i < 10; i++) {
212234
Thread.sleep(1000L);
213-
logger.info("{}", idWorkerPatchi.nextId());
235+
logger.info("{}", idWorkerPatch.nextId());
214236
}
215237
}
216238

0 commit comments

Comments
 (0)