The structure of snowflake is as follows (each part is separated with -):
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
The first bit is unused, the next 41 bits are millisecond time (the length of 41 bits can be used for 69 years), then 5-bit datacenterId and 5-bit workerid (the length of 10 bits can support the deployment of up to 1024 nodes), and the last 12 bits are the count within milliseconds (the 12-bit count sequence number supports 4096 ID sequence numbers per node per millisecond)
All together, it's just 64 bits. It's a Long type. (maximum length after conversion to string 19)
The IDs generated by snowflake are sorted according to the increasing time on the whole, and there is no ID collision in the whole distributed system (differentiated by datacenter and workerId), and the efficiency is high. Snowflake has been tested to generate 260000 IDS per second.
/** * Twitter_Snowflake<br> * SnowFlake Its structure is as follows (each part is separated by using): < br > * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br> * 1 Bit id: since the long basic type is signed in Java, the highest bit is the sign bit, the positive number is 0, and the negative number is 1, so the id is generally a positive number, and the highest bit is 0 < br > * 41 Bit time section (millisecond level), note that 41 bit time section is not the time section of the current time, but the difference of the storage time section (current time section start time section) * The start time section here is generally the start time of our id generator, which is specified by our program (as follows: the startTime property of IdWorker class of the program below). The 41 bit time period can be used for 69 years, and the year t = (1L < < 41) / (1000L * 60 * 60 * 24 * 365) = 69 < br > * 10 The data machine bit of bit can be deployed in 1024 nodes, including 5-bit datacenterId and 5-bit workerid < br > * 12 Bit sequence, counting within milliseconds, and 12 bit counting sequence number support each node to generate 4096 ID sequence numbers per millisecond (the same machine, the same time cut) < br > * Add up to just 64 bits, a Long type. <br> * SnowFlake The advantage of this method is that the whole system is sorted according to the time increment, and there is no ID collision (distinguished by the data center ID and machine ID) in the whole distributed system, and the efficiency is high. After testing, SnowFlake can generate about 260000 IDS per second. */ public class SnowflakeIdWorker { /** Start time (2010-05-01)*/ private final long twepoch = 1272643200000L; /** Number of digits occupied by machine id */ private final long workerIdBits = 5L; /** Number of digits occupied by data id */ private final long datacenterIdBits = 5L; /** The maximum machine id supported, the result is 31 (this shift algorithm can quickly calculate the maximum decimal number that several binary numbers can represent) */ private final long maxWorkerId = -1L ^ (-1L << workerIdBits); /** Maximum data id supported, result is 31 */ private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); /** Number of digits of sequence in id */ private final long sequenceBits = 12L; /** Machine ID moved 12 bits to the left */ private final long workerIdShift = sequenceBits; /** Move data id 17 bits to the left (12 + 5) */ private final long datacenterIdShift = sequenceBits + workerIdBits; /** Time cut 22 bits left (5 + 5 + 12) */ private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; /** Mask for generating sequence, here is 4095 (0b111111111111=0xfff=4095) */ private final long sequenceMask = -1L ^ (-1L << sequenceBits); /** Working machine ID (0-31) */ private long workerId; /** Data center ID (0-31) */ private long datacenterId; /** Sequence in milliseconds (0-4095) */ private long sequence = 0L; /** Last ID generated by */ private long lastTimestamp = -1L; //==============================Constructors===================================== /** * Constructor * @param workerId Work ID (0-31) * @param datacenterId Data center ID (0-31) */ public SnowflakeIdWorker(long workerId, long datacenterId) { 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)); } this.workerId = workerId; this.datacenterId = datacenterId; } // ==============================Methods========================================== /** * Get the next ID (this method is thread safe) * @return SnowflakeId */ public synchronized long nextId() { long timestamp = timeGen(); //If the current time is less than the time stamp generated by the last ID, an exception should be thrown when the system clock goes back if (timestamp < lastTimestamp) { throw new RuntimeException( String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } //If generated at the same time, sequence in milliseconds if (lastTimestamp == timestamp) { sequence = (sequence + 1) & sequenceMask; //Sequence overflow in MS if (sequence == 0) { //Block to next MS, get new timestamp timestamp = tilNextMillis(lastTimestamp); } } //Timestamp change, sequence reset in MS else { sequence = 0L; } //Last ID generated by lastTimestamp = timestamp; //Shift and combine by or operation to form a 64 bit ID return ((timestamp - twepoch) << timestampLeftShift) // | (datacenterId << datacenterIdShift) // | (workerId << workerIdShift) // | sequence; } /** * Blocks to the next millisecond until a new timestamp is obtained * @param lastTimestamp Last ID generated by * @return Current timestamp */ protected long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } /** * Returns the current time in milliseconds * @return Current time (MS) */ protected long timeGen() { return System.currentTimeMillis(); } //==============================Test============================================= /** test */ public static void main(String[] args) throws Exception{ SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 1); for (int i = 0; i < 1000; i++) { long id = idWorker.nextId(); System.out.println(Long.toBinaryString(id)); System.out.println(id); } } }