SnowFlake algorithm, Twitter is an open source distributed id generation algorithm. Its core idea is: use long-type numbers as a 64 bit globally unique id. Applications in a distributed system is very extensive, and the introduction of ID timestamp, basically to keep from growing.
This 64 bit, where a bit is not used, bit 41 is then used as one of the few milliseconds, with 10 bit as the working machine id, 12 bit as a sequence number.
Let me give you an example, such as the 64 bit below the long-type numbers:
The first part is a bit: 0, this is meaningless, because the first one bit is the sign bit, 1 for negative, 0 for a positive number.
The second part is a 41 bit: indicates the timestamp.
The third part is the 5 bit: indicates that the room id, 10001.
The fourth part is the 5 bit: indicates that the machine id, 1 1001.
The fifth portion 12 is a bit: indicates the number, that is simultaneously generated within a millisecond on a machine room number of id, 000,000,000,000.
In simple terms, you have a service Suppose you want to generate a globally unique id, then you can send a request to deploy the system SnowFlake algorithm by the system SnowFlake algorithm to generate a unique id.
The SnowFlake algorithm system of course, is to know where their rooms and machines, such as room id = 17, the machine id = 12.
Then, after receiving the request, we will use the first bit generated in a manner SnowFlake calculation algorithm of the system a 64 bit long type id, the first bit in the 64 th bit is meaningless.
Then 41 bit, you can use the current timestamp (in milliseconds), and then the upper room 5 id bit set, bit 5 there is disposed on the machine id.
Finally, determine what, in this milliseconds on this machine room a current, which is the first of several requests to the request id generated a cumulative sequence number, as the last 12 bit.
Snow algorithm code:
import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; /** * Snow algorithm */ public class SnowFlake { Private Final static Long twepoch = 12888349746579L ; // machine identification bits Private Final static Long workerIdBits = 5L ; // data center identifier bits Private Final static Long datacenterIdBits = 5L ; // increment the number of bits in the millisecond Private Final static Long sequenceBits 12L = ; // machine ID 12 shift left private Final static Long workerIdShift = sequenceBits; // data center ID 17 left private Final static Long datacenterIdShift + = sequenceBits workerIdBits; // time in milliseconds left 22 Private Final static Long timestampLeftShift workerIdBits + + = sequenceBits datacenterIdBits; // Sequence mask, will not exceed the upper limit to ensure sequnce Private Final static Long sequenceMask ^ = -1L (-1L << sequenceBits); // last timestamp Private static Long LastTimestamp = -1L ; // sequence Private Long sequence = 0L ; // server ID Private long workerId = 1L; private static long workerMask = -1L ^ (-1L << workerIdBits); //进程编码 private long processId = 1L; private static long processMask = -1L ^ (-1L << datacenterIdBits); private static SnowFlake snowFlake = null; static{ snowFlake = new SnowFlake(); } public static synchronized long nextId(){ return snowFlake.getNextId(); } Private Snowflake () { // Get machine code the this .workerId = the this .getMachineNum (); // get the process coding the RuntimeMXBean RuntimeMXBean = ManagementFactory.getRuntimeMXBean (); the this . .processId = Long.valueOf (runtimeMXBean.getName () Split ( "@") [0 ]) longValue in ().; // to avoid exceeding the maximum encoding the this .workerId = workerId & workerMask; the this .processId = processId & processMask; } public the synchronized Long getNextId () { // Get timestamp Long timestamp = TIMEGEN (); // if the timestamp is lower than the previous timestamp error IF (timestamp < LastTimestamp) { the try { the throw new new . Exception ( "Clock Backwards refusing Moved Generate for ID to "+ (LastTimestamp - timestamp) +" milliseconds " ); } catch (Exception e) { e.printStackTrace (); } } // If the timestamp and the timestamp of the last time the same IF (LastTimestamp == timestamp) { // the current milliseconds, +1, and sequence to ensure that does not exceed the upper limit sequenceMask sequence = (+ sequence. 1) & sequenceMask; IF (sequence == 0 ) { // this millisecond count is full, the next second waiting timestamp = tilNextMillis (LastTimestamp); } } else { sequence = 0; } LastTimestamp = timestamp; // ID offset composition generate a final ID, and returns the ID Long nextId = ((timestamp - twepoch) << timestampLeftShift) | (processId << datacenterIdShift) | (workerId << workerIdShift) | Sequence; return nextId ; } /** * Get the timestamp and timestamp again until the acquisition of different existing * @Param LastTimestamp * @Return next timestamp * / Private Long tilNextMillis ( Final Long LastTimestamp) { Long timestamp = the this .timeGen (); the while (timestamp <= LastTimestamp) { timestamp = this.timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } /** * Get machine code * @return */ private long getMachineNum(){ long machinePiece; StringBuilder sb = new StringBuilder(); Enumeration<NetworkInterface> e = null; try { e = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e1) { e1.printStackTrace (); } while (e.hasMoreElements()) { NetworkInterface ni = e.nextElement(); sb.append(ni.toString()); } machinePiece = sb.toString().hashCode(); return machinePiece; } public static void main(String[] args) { new SnowFlake().getNextId(); } }
Reference: https://blog.csdn.net/lq18050010830/article/details/89845790