-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #109 from TeamSynergyy/feature/idgenerator
- 분산 데이터베이스 객체 ID , 대체키 반영 #87
- Loading branch information
Showing
51 changed files
with
460 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
src/main/java/com/seoultech/synergybe/domain/common/generator/IdGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.seoultech.synergybe.domain.common.generator; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public interface IdGenerator { | ||
Long generateId(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
src/main/java/com/seoultech/synergybe/domain/common/generator/IdGeneratorSnowFlake.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package com.seoultech.synergybe.domain.common.generator; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
import java.net.NetworkInterface; | ||
import java.security.SecureRandom; | ||
import java.time.Instant; | ||
import java.util.Enumeration; | ||
|
||
/** | ||
* Distributed Sequence Generator. | ||
* Inspired by Twitter snowflake: https://github.com/twitter/snowflake/tree/snowflake-2010 | ||
* | ||
* This class should be used as a Singleton. | ||
* Make sure that you create and reuse a Single instance of Snowflake per node in your distributed system cluster. | ||
*/ | ||
@Component | ||
public class IdGeneratorSnowFlake implements IdGenerator { | ||
private static final int UNUSED_BITS = 1; // Sign bit, Unused (always set to 0) | ||
private static final int EPOCH_BITS = 41; | ||
private static final int NODE_ID_BITS = 10; | ||
private static final int SEQUENCE_BITS = 12; | ||
|
||
private static final long maxNodeId = (1L << NODE_ID_BITS) - 1; | ||
private static final long maxSequence = (1L << SEQUENCE_BITS) - 1; | ||
|
||
// Custom Epoch (January 1, 2015 Midnight UTC = 2015-01-01T00:00:00Z) | ||
private static final long DEFAULT_CUSTOM_EPOCH = 1420070400000L; | ||
|
||
private final long nodeId; | ||
private final long customEpoch; | ||
|
||
private volatile long lastTimestamp = -1L; | ||
private volatile long sequence = 0L; | ||
|
||
// Create Snowflake with a nodeId and custom epoch | ||
public IdGeneratorSnowFlake(long nodeId, long customEpoch) { | ||
if(nodeId < 0 || nodeId > maxNodeId) { | ||
throw new IllegalArgumentException(String.format("NodeId must be between %d and %d", 0, maxNodeId)); | ||
} | ||
this.nodeId = nodeId; | ||
this.customEpoch = customEpoch; | ||
} | ||
|
||
// Create Snowflake with a nodeId | ||
public IdGeneratorSnowFlake(long nodeId) { | ||
this(nodeId, DEFAULT_CUSTOM_EPOCH); | ||
} | ||
|
||
// Let Snowflake generate a nodeId | ||
public IdGeneratorSnowFlake() { | ||
this.nodeId = createNodeId(); | ||
this.customEpoch = DEFAULT_CUSTOM_EPOCH; | ||
} | ||
|
||
public Long generateId() { | ||
long id = nextId(); | ||
return id; | ||
} | ||
|
||
public synchronized long nextId() { | ||
long currentTimestamp = timestamp(); | ||
|
||
if(currentTimestamp < lastTimestamp) { | ||
throw new IllegalStateException("Invalid System Clock!"); | ||
} | ||
|
||
if (currentTimestamp == lastTimestamp) { | ||
sequence = (sequence + 1) & maxSequence; | ||
if(sequence == 0) { | ||
// Sequence Exhausted, wait till next millisecond. | ||
currentTimestamp = waitNextMillis(currentTimestamp); | ||
} | ||
} else { | ||
// reset sequence to start with zero for the next millisecond | ||
sequence = 0; | ||
} | ||
|
||
lastTimestamp = currentTimestamp; | ||
|
||
long id = currentTimestamp << (NODE_ID_BITS + SEQUENCE_BITS) | ||
| (nodeId << SEQUENCE_BITS) | ||
| sequence; | ||
|
||
return id; | ||
} | ||
|
||
|
||
// Get current timestamp in milliseconds, adjust for the custom epoch. | ||
private long timestamp() { | ||
return Instant.now().toEpochMilli() - customEpoch; | ||
} | ||
|
||
// Block and wait till next millisecond | ||
private long waitNextMillis(long currentTimestamp) { | ||
while (currentTimestamp == lastTimestamp) { | ||
currentTimestamp = timestamp(); | ||
} | ||
return currentTimestamp; | ||
} | ||
|
||
private long createNodeId() { | ||
long nodeId; | ||
try { | ||
StringBuilder sb = new StringBuilder(); | ||
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); | ||
while (networkInterfaces.hasMoreElements()) { | ||
NetworkInterface networkInterface = networkInterfaces.nextElement(); | ||
byte[] mac = networkInterface.getHardwareAddress(); | ||
if (mac != null) { | ||
for(byte macPort: mac) { | ||
sb.append(String.format("%02X", macPort)); | ||
} | ||
} | ||
} | ||
nodeId = sb.toString().hashCode(); | ||
} catch (Exception ex) { | ||
nodeId = (new SecureRandom().nextInt()); | ||
} | ||
nodeId = nodeId & maxNodeId; | ||
return nodeId; | ||
} | ||
|
||
public long[] parse(long id) { | ||
long maskNodeId = ((1L << NODE_ID_BITS) - 1) << SEQUENCE_BITS; | ||
long maskSequence = (1L << SEQUENCE_BITS) - 1; | ||
|
||
long timestamp = (id >> (NODE_ID_BITS + SEQUENCE_BITS)) + customEpoch; | ||
long nodeId = (id & maskNodeId) >> SEQUENCE_BITS; | ||
long sequence = id & maskSequence; | ||
|
||
return new long[]{timestamp, nodeId, sequence}; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Snowflake Settings [EPOCH_BITS=" + EPOCH_BITS + ", NODE_ID_BITS=" + NODE_ID_BITS | ||
+ ", SEQUENCE_BITS=" + SEQUENCE_BITS + ", CUSTOM_EPOCH=" + customEpoch | ||
+ ", NodeId=" + nodeId + "]"; | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...e/domain/common/idgenerator/IdPrefix.java → ...ybe/domain/common/generator/IdPrefix.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
src/main/java/com/seoultech/synergybe/domain/common/generator/TokenGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.seoultech.synergybe.domain.common.generator; | ||
|
||
public interface TokenGenerator { | ||
String generateToken(IdPrefix idPrefix); | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/com/seoultech/synergybe/domain/common/generator/TokenGeneratorUUID.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.seoultech.synergybe.domain.common.generator; | ||
|
||
import com.fasterxml.uuid.Generators; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.UUID; | ||
|
||
@Component | ||
public class TokenGeneratorUUID implements TokenGenerator { | ||
|
||
public String generateToken(IdPrefix idPrefix) { | ||
UUID originUuid = Generators.timeBasedGenerator().generate(); | ||
String[] uuidArr = originUuid.toString().split("-"); | ||
String uuidStr = uuidArr[2] + uuidArr[1] + uuidArr[0] + uuidArr[3] + uuidArr[4]; | ||
String uuid = idPrefix.getValue() + "_" + uuidStr; | ||
return uuid; | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/main/java/com/seoultech/synergybe/domain/common/generator/UUIDConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.seoultech.synergybe.domain.common.generator; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
import java.nio.ByteBuffer; | ||
import java.util.UUID; | ||
|
||
@Component | ||
public class UUIDConverter { | ||
// UUID를 BINARY(16)로 변환 | ||
public static byte[] toBinaryUUID(UUID uuid) { | ||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]); | ||
bb.putLong(uuid.getMostSignificantBits()); | ||
bb.putLong(uuid.getLeastSignificantBits()); | ||
return bb.array(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
src/main/java/com/seoultech/synergybe/domain/follow/service/FollowService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.