|
10 | 10 | * 如果ID生成不频繁,则生成的就是全是偶数
|
11 | 11 | * 改良版雪花算法,解决全为偶数问题,保证低并发时奇偶交替
|
12 | 12 | *
|
| 13 | + * 时钟回拨问题直接抛出异常,过于简单 |
| 14 | + * 优化如果时间偏差大小小于5ms,则等待两倍时间重试一次,加强可用性 |
| 15 | + * |
13 | 16 | * SnowFlake的结构如下(每部分用-分开):<br>
|
14 | 17 | * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
|
15 | 18 | * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
|
@@ -140,9 +143,28 @@ public synchronized long nextId() {
|
140 | 143 |
|
141 | 144 | // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
|
142 | 145 | if (timestamp < lastTimestamp) {
|
143 |
| - logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp); |
144 |
| - throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", |
145 |
| - lastTimestamp - timestamp)); |
| 146 | + long offset = lastTimestamp - timestamp; |
| 147 | + if (offset <= 5) { |
| 148 | + try { |
| 149 | + // 时间偏差大小小于5ms,则等待两倍时间重试一次 |
| 150 | + wait(offset << 1); |
| 151 | + timestamp = timeGen(); |
| 152 | + if (timestamp < lastTimestamp) { |
| 153 | + // 还是小于,抛异常 |
| 154 | + logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp); |
| 155 | + throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", |
| 156 | + lastTimestamp - timestamp)); |
| 157 | + } |
| 158 | + } catch (InterruptedException e) { |
| 159 | + logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp); |
| 160 | + throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", |
| 161 | + lastTimestamp - timestamp)); |
| 162 | + } |
| 163 | + } else { |
| 164 | + logger.error("clock is moving backwards. Rejecting requests until {}.", lastTimestamp); |
| 165 | + throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", |
| 166 | + lastTimestamp - timestamp)); |
| 167 | + } |
146 | 168 | }
|
147 | 169 |
|
148 | 170 | // 如果是同一时间生成的,则进行毫秒内序列
|
@@ -206,10 +228,10 @@ private long timeGen() {
|
206 | 228 | * @throws Exception
|
207 | 229 | */
|
208 | 230 | public static void main(String[] args) throws Exception {
|
209 |
| - IdWorkerPatch idWorkerPatchi = new IdWorkerPatch(15L, 15L, 0L); |
| 231 | + IdWorkerPatch idWorkerPatch = new IdWorkerPatch(15L, 15L, 0L); |
210 | 232 | for (int i = 0; i < 10; i++) {
|
211 | 233 | Thread.sleep(1000L);
|
212 |
| - logger.info("{}", idWorkerPatchi.nextId()); |
| 234 | + logger.info("{}", idWorkerPatch.nextId()); |
213 | 235 | }
|
214 | 236 | }
|
215 | 237 |
|
|
0 commit comments