In our work, some field in the database table will be used only trend increasing order number, we will introduce two methods, one is the traditional way of using a random number generator, the other is the use of the current relatively popular "distributed generation algorithm unique ID - snow algorithm" to achieve.
First, the random number generation timestamp unique ID
We write a for loop, generating 1000 unique ID with RandomUtil.generateOrderCode (), the results we will find duplicate ID appears.
/ ** * random number generation util * / public class RandomUtil { Private static new new = Final the SimpleDateFormat dateFormatOne the SimpleDateFormat ( "yyyyMMddHHmmssSS"); Private Final ThreadLocalRandom static Random ThreadLocalRandom.current = (); // generated order number - a way public String generateOrderCode static () { // the TODO: timestamp + N random sequence number return dateFormatOne.format generateNumber + (. 4) (DateTime.Now () toDate ().); } // random sequence number N public String generateNumber static (Final NUM int) { the StringBuffer the StringBuffer new new SB = (); for (int I =. 1; I <= NUM; I ++) { sb.append (random.nextInt (. 9)); } return sb.toString () ; } }
In view of this, "based on a random number generation" approach in a highly concurrent scenario does not meet our requirements, then we will introduce another more popular, the typical way that a "distributed generation algorithm unique ID - snow algorithm "to achieve.
For introduction "snowflake method", the junior partner you can refer to this link on Github, I think it speaks quite clear: https://github.com/souyunku/SnowFlake , detailed here will not go into Debug the following section summarizes the interception of:
Second, distributed unique ID generation algorithm - algorithm Snow
We write a for loop, generating 1000 unique ID with SNOW_FLAKE.nextId (), it will not be found duplicate.
/ ** * algorithm snow
* / public class Snowflake { // start timestamp Private Long START_STAMP = Final static 1480166465631L; // number of bits occupied by each portion private final static long SEQUENCE_BIT = 12; // bit serial number occupies the number of private final static long MACHINE_BIT = 5; // machine identification number of bits occupied by the private final static long DATA_CENTER_BIT = 5; // number of bits occupied by the data center // maximum value of each part of the private final static long MAX_DATA_CENTER_NUM = -1L ^ ( << DATA_CENTER_BIT -1L); private static Long MAX_MACHINE_NUM Final -1L = ^ (-1L << MACHINE_BIT); private static Long MAX_SEQUENCE Final -1L = ^ (-1L << SEQUENCE_BIT); // for each portion of the displaced leftward private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT ; private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT; private long dataCenterId; //数据中心 private long machineId; //机器标识 private long sequence = 0L; //序列号 private long lastStamp = -1L;//上一次时间戳 public SnowFlake(long dataCenterId, long machineId) { if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) { throw new IllegalArgumentException("dataCenterId can't be greater than MAX_DATA_CENTER_NUM or less than 0"); } if (machineId > MAX_MACHINE_NUM || machineId < 0) { new new an IllegalArgumentException the throw ( "CAN Not BE MachineID Within last MAX_MACHINE_NUM Greater or less Within last 0"); } } this.dataCenterId = dataCenterId; = MachineID this.machineId; } // generate the next ID public nextId the synchronized Long () { Long currStamp getNewStamp = (); IF (currStamp <lastStamp) { the throw a RuntimeException new new ( "Clock Moved Backwards refusing to Generate ID."); } IF (currStamp == lastStamp) { // within the same ms, the sequence number incremented sequence = (sequence + 1) & MAX_SEQUENCE; sequence number // ms has reached the same maximum IF (sequence == 0L) { currStamp = getNextMill (); lastStamp = currStamp; } Else { the different // ms, the sequence number is set to 0 Sequence = 0L; } } return (currStamp - START_STAMP) << TIMESTAMP_LEFT // stamp component | dataCenterId << DATA_CENTER_LEFT // data center portion | machineId << MACHINE_LEFT // machine identification section | sequence; // portion of SEQ ID NO } Private Long getNextMill () { Long = getNewStamp Mill (); the while (Mill <= lastStamp) { Mill getNewStamp = (); } return Mill; } Private Long getNewStamp () { return System.currentTimeMillis (); }
In summary, we have a large number of concurrent high to generate a unique ID, to avoid generating duplicate ID, you need to generate a second snowflakes algorithm.