Sequence.java 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /**
  2. * Copyright (c) 2011-2020, hubin (jobob@qq.com).
  3. * <p>
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. * <p>
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. * <p>
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.baomidou.mybatisplus.toolkit;
  17. import java.lang.management.ManagementFactory;
  18. import java.net.InetAddress;
  19. import java.net.NetworkInterface;
  20. import java.util.concurrent.ThreadLocalRandom;
  21. import org.apache.ibatis.logging.Log;
  22. import org.apache.ibatis.logging.LogFactory;
  23. import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
  24. import com.baomidou.mybatisplus.plugins.SqlExplainInterceptor;
  25. /**
  26. * <p>
  27. * 分布式高效有序ID生产黑科技(sequence) <br>
  28. * 优化开源项目:http://git.oschina.net/yu120/sequence
  29. * </p>
  30. *
  31. * @author hubin
  32. * @date 2016-08-18
  33. */
  34. public class Sequence {
  35. private static final Log logger = LogFactory.getLog(SqlExplainInterceptor.class);
  36. /* 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) */
  37. private final long twepoch = 1288834974657L;
  38. private final long workerIdBits = 5L;/* 机器标识位数 */
  39. private final long datacenterIdBits = 5L;
  40. private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
  41. private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
  42. private final long sequenceBits = 12L;/* 毫秒内自增位 */
  43. private final long workerIdShift = sequenceBits;
  44. private final long datacenterIdShift = sequenceBits + workerIdBits;
  45. /* 时间戳左移动位 */
  46. private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
  47. private final long sequenceMask = -1L ^ (-1L << sequenceBits);
  48. private long workerId;
  49. /* 数据标识id部分 */
  50. private long datacenterId;
  51. private long sequence = 0L;/* 0,并发控制 */
  52. private long lastTimestamp = -1L;/* 上次生产id时间戳 */
  53. public Sequence() {
  54. this.datacenterId = getDatacenterId(maxDatacenterId);
  55. this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
  56. }
  57. /**
  58. * @param workerId 工作机器ID
  59. * @param datacenterId 序列号
  60. */
  61. public Sequence(long workerId, long datacenterId) {
  62. if (workerId > maxWorkerId || workerId < 0) {
  63. throw new MybatisPlusException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
  64. }
  65. if (datacenterId > maxDatacenterId || datacenterId < 0) {
  66. throw new MybatisPlusException(
  67. String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
  68. }
  69. this.workerId = workerId;
  70. this.datacenterId = datacenterId;
  71. }
  72. /**
  73. * <p>
  74. * 获取 maxWorkerId
  75. * </p>
  76. */
  77. protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
  78. StringBuilder mpid = new StringBuilder();
  79. mpid.append(datacenterId);
  80. String name = ManagementFactory.getRuntimeMXBean().getName();
  81. if (StringUtils.isNotEmpty(name)) {
  82. /*
  83. * GET jvmPid
  84. */
  85. mpid.append(name.split("@")[0]);
  86. }
  87. /*
  88. * MAC + PID 的 hashcode 获取16个低位
  89. */
  90. return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
  91. }
  92. /**
  93. * <p>
  94. * 数据标识id部分
  95. * </p>
  96. */
  97. protected static long getDatacenterId(long maxDatacenterId) {
  98. long id = 0L;
  99. try {
  100. InetAddress ip = InetAddress.getLocalHost();
  101. NetworkInterface network = NetworkInterface.getByInetAddress(ip);
  102. if (network == null) {
  103. id = 1L;
  104. } else {
  105. byte[] mac = network.getHardwareAddress();
  106. id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
  107. id = id % (maxDatacenterId + 1);
  108. }
  109. } catch (Exception e) {
  110. logger.warn(" getDatacenterId: " + e.getMessage());
  111. }
  112. return id;
  113. }
  114. /**
  115. * 获取下一个ID
  116. *
  117. * @return
  118. */
  119. public synchronized long nextId() {
  120. long timestamp = timeGen();
  121. if (timestamp < lastTimestamp) {//闰秒
  122. long offset = lastTimestamp - timestamp;
  123. if (offset <= 5) {
  124. try {
  125. wait(offset << 1);
  126. timestamp = timeGen();
  127. if (timestamp < lastTimestamp) {
  128. throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
  129. }
  130. } catch (Exception e) {
  131. throw new RuntimeException(e);
  132. }
  133. } else {
  134. throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
  135. }
  136. }
  137. if (lastTimestamp == timestamp) {
  138. // 相同毫秒内,序列号自增
  139. sequence = (sequence + 1) & sequenceMask;
  140. if (sequence == 0) {
  141. // 同一毫秒的序列数已经达到最大
  142. timestamp = tilNextMillis(lastTimestamp);
  143. }
  144. } else {
  145. // 不同毫秒内,序列号置为 1 - 3 随机数
  146. sequence = ThreadLocalRandom.current().nextLong(1, 3);
  147. }
  148. lastTimestamp = timestamp;
  149. return ((timestamp - twepoch) << timestampLeftShift) // 时间戳部分
  150. | (datacenterId << datacenterIdShift) // 数据中心部分
  151. | (workerId << workerIdShift) // 机器标识部分
  152. | sequence; // 序列号部分
  153. }
  154. protected long tilNextMillis(long lastTimestamp) {
  155. long timestamp = timeGen();
  156. while (timestamp <= lastTimestamp) {
  157. timestamp = timeGen();
  158. }
  159. return timestamp;
  160. }
  161. protected long timeGen() {
  162. return SystemClock.now();
  163. }
  164. }