Skip to content

Instantly share code, notes, and snippets.

@ryantenney
Created January 26, 2012 22:49
Show Gist options
  • Select an option

  • Save ryantenney/1685616 to your computer and use it in GitHub Desktop.

Select an option

Save ryantenney/1685616 to your computer and use it in GitHub Desktop.
package us.t4y.scratch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Adapted from Twitter's Snowflake
* http://github.com/twitter/snowflake
*/
public class Snowflake {
private static final Logger log = LoggerFactory.getLogger(Snowflake.class);
private static final long epoch = 1288834974657L;
private static final long workerIdBits = 5L;
private static final long datacenterIdBits = 5L;
private static final long sequenceBits = 12L;
private static final long workerIdShift = sequenceBits;
private static final long datacenterIdShift = sequenceBits + workerIdBits;
private static final long timestampShift = sequenceBits + workerIdBits + datacenterIdBits;
private static final long sequenceMask = -1L ^ (-1L << sequenceBits);
private static final long workerIdMask = -1L ^ (-1L << workerIdBits);
private static final long datacenterIdMask = -1L ^ (-1L << datacenterIdBits);
private final long workerId;
private final long datacenterId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public Snowflake(final long datacenterId, final long workerId) {
this.datacenterId = datacenterId & datacenterIdMask;
this.workerId = workerId & workerIdMask;
}
public synchronized long nextId() {
long timestamp = timestamp();
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
System.out.println("rollover");
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
if (timestamp < lastTimestamp) {
log.error("Clock is moving backwards. Rejecting requests until " + lastTimestamp + ".");
throw new IllegalStateException("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds");
}
lastTimestamp = timestamp;
return ((timestamp - epoch) << timestampShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timestamp();
while (timestamp <= lastTimestamp) {
timestamp = timestamp();
}
return timestamp;
}
protected long timestamp() {
return System.currentTimeMillis();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment