Last active
December 4, 2020 20:58
-
-
Save bflorat/d7d152059b65844531b3c69e4438d00e to your computer and use it in GitHub Desktop.
sequential UUID using current time.Based on https://blog.2ndquadrant.com/sequential-uuid-generators/
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
package uuid; | |
import java.nio.ByteBuffer; | |
import java.security.SecureRandom; | |
import java.time.Instant; | |
import java.util.UUID; | |
public class OtherUUIDUtil { | |
private static final int UUID_LENGTH = 16; | |
private static final int DEFAULT_INTERVAL_LENGTH = 60; | |
private static final int DEFAULT_INTERAVL_COUNT = 65536; | |
private static volatile SecureRandom numberGenerator = null; | |
/** | |
* Static factory to generate sequential UUID using current time | |
* <p> | |
* The timestamp-based sequential UUID generator define the group size and group | |
* count based on data extracted from current timestamp. | |
* <p> | |
* The interval_length (60 seconds by default) is defined as number of seconds | |
* where UUIDs share the same prefix). The prefix length is determined by the | |
* number of intervals (65536 by default, i.e. 2B). With these parameters the | |
* generator wraps around every ~45 days. | |
* | |
* @return A sequentialy generated {@code UUID} using current time | |
*/ | |
public static UUID timeUUID() { | |
return timeUUID(DEFAULT_INTERVAL_LENGTH, DEFAULT_INTERAVL_COUNT); | |
} | |
/** | |
* Static factory to generate sequential UUID using current time | |
* <p> | |
* The timestamp-based sequential UUID generator define the group size and group | |
* count based on data extracted from current timestamp. | |
* | |
* @param intervalLength | |
* The number of seconds where {@code UUID} share the same prefix | |
* @param intervalCount | |
* Used to derive the prefix length | |
* @return A sequentialy generated {@code UUID} using current time | |
*/ | |
public static UUID timeUUID(int intervalLength, int intervalCount) { | |
assert intervalLength > 1 : "length of interval must be a positive integer"; | |
assert intervalCount > 1 : "number of intervals must be a positive integer"; | |
SecureRandom ng = numberGenerator; | |
if (ng == null) | |
numberGenerator = ng = new SecureRandom(); | |
int i; | |
ByteBuffer buffer = ByteBuffer.allocate(UUID_LENGTH); | |
long epoch = Instant.now().getEpochSecond(); | |
byte[] val = longToTwoLeastSignificantBytes(epoch / intervalLength); | |
int prefixBytes = 0; | |
while (intervalCount > 1) { | |
intervalCount /= 256; | |
prefixBytes++; | |
} | |
for (i = 0; i < prefixBytes; i++) | |
buffer.put(i, val[prefixBytes - 1 - i]); | |
byte[] randomBytes = new byte[UUID_LENGTH - prefixBytes]; | |
ng.nextBytes(randomBytes); | |
for (i = 0; i < randomBytes.length; i++) | |
buffer.put(i + prefixBytes, randomBytes[i]); | |
return new UUID(buffer.getLong(), buffer.getLong()); | |
} | |
public static byte[] longToTwoLeastSignificantBytes(long l) { | |
byte[] result = new byte[2]; | |
result[0] = (byte) (l & 0xFF); | |
result[1] = (byte) ((l >> 8) & 0xFF); | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment