zoukankan      html  css  js  c++  java
  • 生成主键ID,唯一键id,分布式ID生成器雪花算法代码实现

    工具类: 

    1. package com.ihrm.common.utils;
    2. import java.lang.management.ManagementFactory;
    3. import java.net.InetAddress;
    4. import java.net.NetworkInterface;
    5. //雪花算法代码实现
    6. public class IdWorker {
    7. // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
    8. private final static long twepoch = 1288834974657L;
    9. // 机器标识位数
    10. private final static long workerIdBits = 5L;
    11. // 数据中心标识位数
    12. private final static long datacenterIdBits = 5L;
    13. // 机器ID最大值
    14. private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
    15. // 数据中心ID最大值
    16. private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    17. // 毫秒内自增位
    18. private final static long sequenceBits = 12L;
    19. // 机器ID偏左移12位
    20. private final static long workerIdShift = sequenceBits;
    21. // 数据中心ID左移17位
    22. private final static long datacenterIdShift = sequenceBits + workerIdBits;
    23. // 时间毫秒左移22位
    24. private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    25. private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
    26. /* 上次生产id时间戳 */
    27. private static long lastTimestamp = -1L;
    28. // 0,并发控制
    29. private long sequence = 0L;
    30. private final long workerId;
    31. // 数据标识id部分
    32. private final long datacenterId;
    33. public IdWorker(){
    34. this.datacenterId = getDatacenterId(maxDatacenterId);
    35. this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
    36. }
    37. /**
    38. * @param workerId
    39. * 工作机器ID
    40. * @param datacenterId
    41. * 序列号
    42. */
    43. public IdWorker(long workerId, long datacenterId) {
    44. if (workerId > maxWorkerId || workerId < 0) {
    45. throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
    46. }
    47. if (datacenterId > maxDatacenterId || datacenterId < 0) {
    48. throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
    49. }
    50. this.workerId = workerId;
    51. this.datacenterId = datacenterId;
    52. }
    53. /**
    54. * 获取下一个ID
    55. *
    56. * @return
    57. */
    58. public synchronized long nextId() {
    59. long timestamp = timeGen();
    60. if (timestamp < lastTimestamp) {
    61. throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
    62. }
    63. if (lastTimestamp == timestamp) {
    64. // 当前毫秒内,则+1
    65. sequence = (sequence + 1) & sequenceMask;
    66. if (sequence == 0) {
    67. // 当前毫秒内计数满了,则等待下一秒
    68. timestamp = tilNextMillis(lastTimestamp);
    69. }
    70. } else {
    71. sequence = 0L;
    72. }
    73. lastTimestamp = timestamp;
    74. // ID偏移组合生成最终的ID,并返回ID
    75. long nextId = ((timestamp - twepoch) << timestampLeftShift)
    76. | (datacenterId << datacenterIdShift)
    77. | (workerId << workerIdShift) | sequence;
    78. return nextId;
    79. }
    80. private long tilNextMillis(final long lastTimestamp) {
    81. long timestamp = this.timeGen();
    82. while (timestamp <= lastTimestamp) {
    83. timestamp = this.timeGen();
    84. }
    85. return timestamp;
    86. }
    87. private long timeGen() {
    88. return System.currentTimeMillis();
    89. }
    90. /**
    91. * <p>
    92. * 获取 maxWorkerId
    93. * </p>
    94. */
    95. protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
    96. StringBuffer mpid = new StringBuffer();
    97. mpid.append(datacenterId);
    98. String name = ManagementFactory.getRuntimeMXBean().getName();
    99. if (!name.isEmpty()) {
    100. /*
    101. * GET jvmPid
    102. */
    103. mpid.append(name.split("@")[0]);
    104. }
    105. /*
    106. * MAC + PID 的 hashcode 获取16个低位
    107. */
    108. return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
    109. }
    110. /**
    111. * <p>
    112. * 数据标识id部分
    113. * </p>
    114. */
    115. protected static long getDatacenterId(long maxDatacenterId) {
    116. long id = 0L;
    117. try {
    118. InetAddress ip = InetAddress.getLocalHost();
    119. NetworkInterface network = NetworkInterface.getByInetAddress(ip);
    120. if (network == null) {
    121. id = 1L;
    122. } else {
    123. byte[] mac = network.getHardwareAddress();
    124. id = ((0x000000FF & (long) mac[mac.length - 1])
    125. | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
    126. id = id % (maxDatacenterId + 1);
    127. }
    128. } catch (Exception e) {
    129. System.out.println(" getDatacenterId: " + e.getMessage());
    130. }
    131. return id;
    132. }
    133. }

    使用:

    1. IdWorker idWorker = new IdWorker();
    2. long id = idWorker.nextId();
  • 相关阅读:
    485串口接线
    mvc3 升级mvc5
    VB连接ACCESS数据库,使用 LIKE 通配符问题
    VB6 读写西门子PLC
    可用的 .net core 支持 RSA 私钥加密工具类
    解决 Win7 远程桌面 已停止工作的问题
    解决 WinForm 重写 CreateParams 隐藏窗口以后的显示问题
    解决安装 .net framework 发生 extracting files error 问题
    CentOS7 安装配置笔记
    通过特殊处理 Resize 事件解决 WinForm 加载时闪烁问题的一个方法
  • 原文地址:https://www.cnblogs.com/jpfss/p/11190431.html
Copyright © 2011-2022 走看看