• 生成主键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();
  • 相关阅读:
    net过滤表单和url参数
    html mailto
    sql提取汉字拼音首字母
    使用jquery获取radio的值
    net文件服务器配置
    如何将简体字保存到繁体数据库而不会出现乱码
    net直接下载文件
    java开发:笔记
    android开发:LogCat失效,adb失效
    编程记事本
  • 原文地址:https://www.cnblogs.com/jpfss/p/11190431.html
Copyright © 2020-2023  润新知