## 编程知识 cdmana.com

### Snowflake algorithm to generate ID

Snowflake algorithm id It's a long Type of   Convert to binary yes 64 position

0   |      00000000000000000000000000000000000000000  |   0000000000|    000000000000

The first part ： first place 0 The sign bit     Because of the id All positive numbers.   So the first one is 0  （ Mark positive and negative with the first digit 1 A negative number 0 It means a positive number ）

The second part ：00000000000000000000000000000000000000000  This 41 Bit represents the timestamp of the current server Millisecond value   Because the millisecond value is converted to binary Namely 41 position     The maximum value of the timestamp   It's about 70 year

The third part ：  0000000000  this 10 In a The top five signs machine id  The last five digits indicate colony id    That is to say, machines id The maximum is 2 Of 5 The power minus 1 That is to say 31  colony id The maximum is also 31

The fourth part ：000000000000 this 12 Who said Sequence     12 All places are 1 At most 4095    in other words Each machine   Every millisecond can generate at most 4095 individual id

Code example

``````package com.xiao;

public class IdWorker{

// Each of the following two 5 position , Add up to 10 Bit working machine id
private long workerId;    // Work id
private long datacenterId;   // data id
//12 Bit's serial number
private long sequence;

public IdWorker(long workerId, long datacenterId, long sequence){
// sanity check for workerId
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0",maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0",maxDatacenterId));
}
System.out.printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",
timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId);

this.workerId = workerId;
this.datacenterId = datacenterId;
this.sequence = sequence;
}

// Initial timestamp
private long twepoch = 1288834974657L;

// The length is 5 position
private long workerIdBits = 5L;
private long datacenterIdBits = 5L;
// Maximum
private long maxWorkerId = -1L ^ (-1L << workerIdBits);
private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
// Serial number id length
private long sequenceBits = 12L;
// Maximum serial number
private long sequenceMask = -1L ^ (-1L << sequenceBits);

// Work id The number of digits that need to be shifted left ,12 position
private long workerIdShift = sequenceBits;
// data id You need to shift the number of digits to the left  12+5=17 position
private long datacenterIdShift = sequenceBits + workerIdBits;
// Timestamps need to be shifted to the left  12+5+5=22 position
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

// Last time stamp , The initial value is negative
private long lastTimestamp = -1L;

public long getWorkerId(){
return workerId;
}

public long getDatacenterId(){
return datacenterId;
}

public long getTimestamp(){
return System.currentTimeMillis();
}

// next ID generating algorithm
public synchronized long nextId() {
long timestamp = timeGen();

// Get the current time stamp. If it is less than the last time stamp , Indicates that there is an exception in timestamp acquisition
if (timestamp < lastTimestamp) {
System.err.printf("clock is moving backwards.  Rejecting requests until %d.", lastTimestamp);
throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds",
lastTimestamp - timestamp));
}

// Get the current time stamp if it is equal to the last time stamp
// explain ： Still in the same millisecond , Add... To the serial number 1; Otherwise, the serial number is assigned to 0, from 0 Start .
if (lastTimestamp == timestamp) {  // 0  - 4095
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}

// Refresh last timestamp value
lastTimestamp = timestamp;

/**
*  Return results ：
* (timestamp - twepoch) << timestampLeftShift)  Indicates that the initial timestamp is subtracted from the timestamp , Move the corresponding digit to the left
* (datacenterId << datacenterIdShift)  It means that the data will be id Move the corresponding digit to the left
* (workerId << workerIdShift)  I'm going to work id Move the corresponding digit to the left
* |  It's a bitwise OR operator , for example ：x | y, Only when x,y All for 0 It turns out to be 0, In other cases, the result is 1.
*  Because only the values in the corresponding bits are meaningful , All the others are 0, So the values of each part are calculated  |  You can get the final stitched id
*/
return ((timestamp - twepoch) << timestampLeftShift) |
(datacenterId << datacenterIdShift) |
(workerId << workerIdShift) |
sequence;
}

// Get the timestamp , And compare with the last timestamp
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}

// Get the system timestamp
private long timeGen(){
return System.currentTimeMillis();
}

public static void main(String[] args) {
IdWorker worker = new IdWorker(31,31,0);
for (int i = 0; i < 100; i++) {
System.out.println(worker.nextId());
}
}

}``````

https://cdmana.com/2020/12/20201225132517929v.html

Scroll to Top