forked from rongchao/epmet-cloud-rizhao
				
			
				 2 changed files with 0 additions and 215 deletions
			
			
		| @ -1,213 +0,0 @@ | |||||
| /* |  | ||||
|  * Copyright (c) 2011-2021, baomidou (jobob@qq.com). |  | ||||
|  * |  | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||
|  * you may not use this file except in compliance with the License. |  | ||||
|  * You may obtain a copy of the License at |  | ||||
|  * |  | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||
|  * |  | ||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||
|  * See the License for the specific language governing permissions and |  | ||||
|  * limitations under the License. |  | ||||
|  */ |  | ||||
| package com.epmet.util; |  | ||||
| 
 |  | ||||
| import com.alibaba.fastjson.JSON; |  | ||||
| import com.baomidou.mybatisplus.core.toolkit.Assert; |  | ||||
| import com.baomidou.mybatisplus.core.toolkit.StringPool; |  | ||||
| import com.baomidou.mybatisplus.core.toolkit.StringUtils; |  | ||||
| import com.baomidou.mybatisplus.core.toolkit.SystemClock; |  | ||||
| import com.epmet.commons.tools.utils.HttpClientManager; |  | ||||
| import lombok.extern.slf4j.Slf4j; |  | ||||
| import org.apache.ibatis.logging.Log; |  | ||||
| import org.apache.ibatis.logging.LogFactory; |  | ||||
| 
 |  | ||||
| import java.lang.management.ManagementFactory; |  | ||||
| import java.net.InetAddress; |  | ||||
| import java.net.NetworkInterface; |  | ||||
| import java.util.concurrent.ThreadLocalRandom; |  | ||||
| 
 |  | ||||
| /** |  | ||||
|  * 分布式高效有序 ID 生产黑科技(sequence) |  | ||||
|  * |  | ||||
|  * <p>优化开源项目:https://gitee.com/yu120/sequence</p>
 |  | ||||
|  * |  | ||||
|  * @author hubin |  | ||||
|  * @since 2016-08-18 |  | ||||
|  */ |  | ||||
| @Slf4j |  | ||||
| public class MySequence { |  | ||||
| 
 |  | ||||
|     private static final Log logger = LogFactory.getLog(MySequence.class); |  | ||||
|     /** |  | ||||
|      * 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) |  | ||||
|      */ |  | ||||
|     private final long twepoch = 1288834974657L; |  | ||||
|     /** |  | ||||
|      * 机器标识位数 |  | ||||
|      */ |  | ||||
|     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 final long workerId; |  | ||||
| 
 |  | ||||
|     /** |  | ||||
|      * 数据标识 ID 部分 |  | ||||
|      */ |  | ||||
|     private final long datacenterId; |  | ||||
|     /** |  | ||||
|      * 并发控制 |  | ||||
|      */ |  | ||||
|     private long sequence = 0L; |  | ||||
|     /** |  | ||||
|      * 上次生产 ID 时间戳 |  | ||||
|      */ |  | ||||
|     private long lastTimestamp = -1L; |  | ||||
| 
 |  | ||||
|     public MySequence() { |  | ||||
|         this.datacenterId = getDatacenterId(maxDatacenterId); |  | ||||
|         this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); |  | ||||
|         String msg = "MySequence datacenterId:" + this.datacenterId + ";workerId:" + this.workerId; |  | ||||
|         log.info(msg); |  | ||||
|         HttpClientManager.getInstance().sendAlarmMsg(msg); |  | ||||
|     } |  | ||||
| 
 |  | ||||
|     /** |  | ||||
|      * 有参构造器 |  | ||||
|      * |  | ||||
|      * @param workerId     工作机器 ID |  | ||||
|      * @param datacenterId 序列号 |  | ||||
|      */ |  | ||||
|     public MySequence(long workerId, long datacenterId) { |  | ||||
|         Assert.isFalse(workerId > maxWorkerId || workerId < 0, |  | ||||
|                 String.format("MySequence worker Id can't be greater than %d or less than 0", maxWorkerId)); |  | ||||
|         Assert.isFalse(datacenterId > maxDatacenterId || datacenterId < 0, |  | ||||
|                 String.format("MySequence datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); |  | ||||
|         this.workerId = workerId; |  | ||||
|         this.datacenterId = datacenterId; |  | ||||
|     } |  | ||||
| 
 |  | ||||
|     /** |  | ||||
|      * 获取 maxWorkerId |  | ||||
|      */ |  | ||||
|     protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { |  | ||||
|         StringBuilder mpid = new StringBuilder(); |  | ||||
|         mpid.append(datacenterId); |  | ||||
|         String name = ManagementFactory.getRuntimeMXBean().getName(); |  | ||||
|         String msg = "MySequence getMaxWorkerId name:" + name; |  | ||||
|         log.info(msg); |  | ||||
|         HttpClientManager.getInstance().sendAlarmMsg(msg); |  | ||||
|         if (StringUtils.isNotBlank(name)) { |  | ||||
|             /* |  | ||||
|              * GET jvmPid |  | ||||
|              */ |  | ||||
|             mpid.append(name.split(StringPool.AT)[0]); |  | ||||
|         } |  | ||||
|         /* |  | ||||
|          * MAC + PID 的 hashcode 获取16个低位 |  | ||||
|          */ |  | ||||
|         return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); |  | ||||
|     } |  | ||||
| 
 |  | ||||
|     /** |  | ||||
|      * 数据标识id部分 |  | ||||
|      */ |  | ||||
|     protected static long getDatacenterId(long maxDatacenterId) { |  | ||||
|         long id = 0L; |  | ||||
|         try { |  | ||||
|             InetAddress ip = InetAddress.getLocalHost(); |  | ||||
|             NetworkInterface network = NetworkInterface.getByInetAddress(ip); |  | ||||
|             String msg = "MySequence ip:" + JSON.toJSONString(ip) + ";network: " + JSON.toJSONString(network); |  | ||||
|             log.info(msg); |  | ||||
|             HttpClientManager.getInstance().sendAlarmMsg(msg); |  | ||||
|             if (network == null) { |  | ||||
|                 id = 1L; |  | ||||
|                 log.info("MySequen cenetwork ==null "); |  | ||||
|             } else { |  | ||||
|                 byte[] mac = network.getHardwareAddress(); |  | ||||
|                 if (null != mac) { |  | ||||
|                     id = ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) >> 6; |  | ||||
|                     id = id % (maxDatacenterId + 1); |  | ||||
|                 } |  | ||||
|             } |  | ||||
|         } catch (Exception e) { |  | ||||
|             logger.warn(" getDatacenterId: " + e.getMessage()); |  | ||||
|         } |  | ||||
|         return id; |  | ||||
|     } |  | ||||
| 
 |  | ||||
|     /** |  | ||||
|      * 获取下一个 ID |  | ||||
|      * |  | ||||
|      * @return 下一个 ID |  | ||||
|      */ |  | ||||
|     public synchronized long nextId() { |  | ||||
|         long timestamp = timeGen(); |  | ||||
|         //闰秒
 |  | ||||
|         if (timestamp < lastTimestamp) { |  | ||||
|             long offset = lastTimestamp - timestamp; |  | ||||
|             if (offset <= 5) { |  | ||||
|                 try { |  | ||||
|                     wait(offset << 1); |  | ||||
|                     timestamp = timeGen(); |  | ||||
|                     if (timestamp < lastTimestamp) { |  | ||||
|                         throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", offset)); |  | ||||
|                     } |  | ||||
|                 } catch (Exception e) { |  | ||||
|                     throw new RuntimeException(e); |  | ||||
|                 } |  | ||||
|             } else { |  | ||||
|                 throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", offset)); |  | ||||
|             } |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         if (lastTimestamp == timestamp) { |  | ||||
|             // 相同毫秒内,序列号自增
 |  | ||||
|             sequence = (sequence + 1) & sequenceMask; |  | ||||
|             if (sequence == 0) { |  | ||||
|                 // 同一毫秒的序列数已经达到最大
 |  | ||||
|                 timestamp = tilNextMillis(lastTimestamp); |  | ||||
|             } |  | ||||
|         } else { |  | ||||
|             // 不同毫秒内,序列号置为 1 - 3 随机数
 |  | ||||
|             sequence = ThreadLocalRandom.current().nextLong(1, 3); |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         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 SystemClock.now(); |  | ||||
|     } |  | ||||
| 
 |  | ||||
| } |  | ||||
					Loading…
					
					
				
		Reference in new issue