Skip to content

Commit 5363b68

Browse files
committed
64 bit sequence generator
1 parent cb61eb1 commit 5363b68

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.gb.didgen.service;
22

3+
import com.gb.didgen.exception.ClockMovedBackException;
4+
35
public interface IdGenerator {
4-
long generateId();
6+
long generateId() throws ClockMovedBackException;
57
}

src/main/java/com/gb/didgen/service/SnowflakeIdGenerator.java

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.gb.didgen.service;
22

3+
import com.gb.didgen.exception.ClockMovedBackException;
34
import com.gb.didgen.exception.NodeIdOutOfBoundException;
45
import lombok.AllArgsConstructor;
56
import org.springframework.stereotype.Service;
@@ -17,11 +18,12 @@ public class SnowflakeIdGenerator implements IdGenerator {
1718
private final int maxSequence = (int) Math.pow(2, SEQUENCE_BIT_LEN);
1819
private final int maxNodeVal = (int) Math.pow(2, NODE_ID_BIT_LEN);
1920

20-
private final long EPOCH = Instant.EPOCH.toEpochMilli();
21+
private final long EPOCH_START = Instant.EPOCH.toEpochMilli();
2122

2223
private final int generatingNodeId;
2324
private volatile long currentSequence;
24-
private volatile long lastTimestamp;
25+
private final Object lock = new Object();
26+
private volatile long lastTimestamp = 0L;
2527

2628
@PostConstruct
2729
public void checkNodeIdBounds() throws NodeIdOutOfBoundException {
@@ -31,7 +33,36 @@ public void checkNodeIdBounds() throws NodeIdOutOfBoundException {
3133
}
3234

3335
@Override
34-
public long generateId() {
35-
return 0;
36+
public long generateId() throws ClockMovedBackException {
37+
synchronized (lock) {
38+
long currentTimeStamp = getTimeStamp();
39+
if (currentTimeStamp < lastTimestamp) {
40+
throw new ClockMovedBackException("Clock moved back");
41+
}
42+
if (currentTimeStamp == lastTimestamp) {
43+
currentSequence = currentSequence + 1 & maxSequence;
44+
if (currentSequence == 0) {
45+
currentTimeStamp = waitNextMillis(currentTimeStamp);
46+
}
47+
} else {
48+
currentSequence = 0;
49+
}
50+
lastTimestamp = currentTimeStamp;
51+
long id = currentTimeStamp << (NODE_ID_BIT_LEN + SEQUENCE_BIT_LEN);
52+
id |= (generatingNodeId << SEQUENCE_BIT_LEN);
53+
id |= currentSequence;
54+
return id;
55+
}
56+
}
57+
58+
private long getTimeStamp() {
59+
return Instant.now().toEpochMilli() - EPOCH_START;
60+
}
61+
62+
private long waitNextMillis(long currentTimeStamp) {
63+
while (currentTimeStamp == lastTimestamp) {
64+
currentTimeStamp = getTimeStamp();
65+
}
66+
return currentTimeStamp;
3667
}
3768
}

0 commit comments

Comments
 (0)