IdGenerator 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 public class IdGenerator { private final long twepoch = 1420041600000L ; private final long workerIdBits = 5L ; private final long datacenterIdBits = 5L ; private final long maxWorkerId = -1L ^ (-1L << workerIdBits); private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); private final long sequenceBits = 12L ; private final long workerIdShift = sequenceBits; private final long datacenterIdShift = sequenceBits + workerIdBits; private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; private final long sequenceMask = -1L ^ (-1L << sequenceBits); private long workerId; private long datacenterId; private long sequence = 0L ; private long lastTimestamp = -1L ; public IdGenerator (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; } public IdGenerator () { this .workerId = 0l ; this .datacenterId = 0l ; } ; public synchronized long nextId () { long timestamp = timeGen(); if (timestamp < lastTimestamp) { throw new RuntimeException ( String.format( "Clock moved backwards. Refusing to generate id for %d milliseconds" , lastTimestamp - timestamp)); } if (lastTimestamp == timestamp) { sequence = (sequence + 1 ) & sequenceMask; if (sequence == 0 ) { timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L ; } lastTimestamp = timestamp; return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; } protected long tilNextMillis (long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } protected long timeGen () { return System.currentTimeMillis(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import cn.hutool.core.lang.Snowflake;import cn.hutool.core.util.IdUtil;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.net.InetAddress;public class IdWorker { private static final Logger logger = LoggerFactory.getLogger(IdWorker.class); public static long nextId () { Snowflake snowflake = IdUtil.getSnowflake(1 , 1 ); return snowflake.nextId(); } public static String nextId (String prefix) { int workerId = 1 ; try { String[] ips = InetAddress.getLocalHost().getHostAddress().split("\\." ); workerId = Integer.parseInt(ips[ips.length - 1 ]); } catch (Exception e) { e.printStackTrace(); } Snowflake snowflake = IdUtil.getSnowflake(workerId % 10 , 1 ); return prefix + snowflake.nextId(); } public static void main (String[] args) { logger.info("" + nextId()); } }
注入如下 service 调用 generatorStoreId() 即可。
1 2 3 public interface IdGeneratorService { Long generatorStoreId () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 import cn.hutool.core.lang.Snowflake;import cn.hutool.core.util.IdUtil;import lombok.SneakyThrows;import lombok.extern.slf4j.Slf4j;import org.redisson.api.RAtomicLong;import org.redisson.api.RLock;import org.redisson.api.RedissonClient;import org.springframework.beans.factory.InitializingBean;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Slf4j @Service public class IdGeneratorServiceImpl implements IdGeneratorService , InitializingBean { private static final String WORK_ID_FORMAT = "id:generator:wordId" ; private static final String SNOW_FLAKE_LOCK = "id:generator:lock" ; private static final String CENTER_ID_FORMAT = "id:generator:center" ; private final int MAX_CENTER_ID = 31 ; private Snowflake snowflake; @Autowired private RedissonClient redissonClient; @SneakyThrows private void generatorWorkAndCenterId () { RLock rLock = redissonClient.getLock(SNOW_FLAKE_LOCK); boolean b = rLock.tryLock(20 , TimeUnit.SECONDS); if (!b) { throw new Exception ("锁超时" ); } try { int workId = getWorkId(); int centerId = getCenterId(workId); snowflake = IdUtil.getSnowflake(workId, centerId); log.info("snowFlake init success centerId:{} workId:{}" , centerId, workId); } finally { rLock.unlock(); } } private int getWorkId () { int workId; RAtomicLong atomicLong = redissonClient.getAtomicLong(WORK_ID_FORMAT); Long l = atomicLong.get(); if (l.intValue() >= MAX_CENTER_ID) { atomicLong.set(0 ); workId = 0 ; } else { l = atomicLong.incrementAndGet(); workId = l.intValue(); } return workId; } private int getCenterId (int workId) { int centerId; RAtomicLong centerAtomicLong = redissonClient.getAtomicLong(CENTER_ID_FORMAT); Long cl = centerAtomicLong.get(); if (workId > 0 ){ centerId = cl.intValue(); }else { if (cl.intValue() >= MAX_CENTER_ID) { centerAtomicLong.set(0 ); centerId = 0 ; } else { cl = centerAtomicLong.incrementAndGet(); centerId = cl.intValue(); } } return centerId; } @Override public Long generatorStoreId () { return snowflake.nextId(); } @Override public void afterPropertiesSet () throws Exception { generatorWorkAndCenterId(); Long snowId = generatorStoreId(); log.info("验证snowflake生成正常,生成id:{}" ,snowId); } }