2.3.4 项目截图
- 后端代码
文章插图
- swagger页面
文章插图
2.3.5 Snowflake雪花算法的代码实现package com.itheima.distributedid.core;import com.itheima.distributedid.core.domain.DistributedIdException;import java.lang.management.ManagementFactory;import java.net.InetAddress;import java.net.NetworkInterface;/** * Twitter的Snowflake算法 * <p> * 协议格式 1: 41位时间戳 2:5位数据中心标识 3:5位机器标识 4:12位序列号 * <p> * 1111111111111111111111111111111 11111 11111 111111111111 */public class Snowflake { //起始时间戳,可以修改为服务器第一次启动的时间 //一旦服务已经开始使用,起始时间戳就不能改变了 , 理论上可以使用69年 private final static long START_TIME = 1484754361114L; /** * 每一个部分占用的位数 */ private final static long SEQUENCE_BIT = 12;//序列号占用的位数 private final static long MACHINE_BIT = 5;//序机器标识 占用的位数 private final static long DATA_CENTER_BIT = 5;//数据中心标识占用的位数 /** * 每一个部分的最大值 11111111111111111 1111111100000 000000000011111 */ private final static long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_BIT); private final static long MAX_MACHINE_ID = ~(-1L << MACHINE_BIT); private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT); /** * 每一部分向左位移数 1111111111111111111111111111111 11111 11111 111111111111 */ private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT; private long dataCenterId;//数据中心ID private long machineId;//数据中心ID private long sequence = 0L;//数据中心ID private long lastTimestamp = -1L;//数据中心ID /** * 分布式部署的时候,数据节点标识和机器标识作为联合键,必须唯一的 * * @param dataCenterId 数据中心标识ID * @param machineId 机器标识ID */ public Snowflake(long dataCenterId, long machineId) { if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) { throw new DistributedIdException("数据中心ID不合法"); } if (machineId > MAX_MACHINE_ID || machineId < 0) { throw new DistributedIdException("机器标识ID不合法"); } this.dataCenterId = dataCenterId; this.machineId = machineId; } /** * 获取下一个ID * * @return */ public synchronized long nextId() { long currentTmestamp = getNowTimestamp(); if (currentTmestamp < lastTimestamp) { throw new RuntimeException("时钟错误,拒绝生成ID"); } if (currentTmestamp == lastTimestamp) { //相同毫秒内,序列号自增 sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列号已经达到最大 if (sequence == 0L) { currentTmestamp = getNexMill(); } } else { //不同毫秒内 , 序列号置为0 sequence = 0L; } lastTimestamp = currentTmestamp; return (currentTmestamp - START_TIME) << TIMESTAMP_LEFT //时间戳的部分 | dataCenterId << DATA_CENTER_LEFT //数据中心的部分 | machineId << MACHINE_LEFT //机器标识的部分 | sequence; //序列号的部分 } /** * 保证获取到的毫秒值是在最后一次分发ID的毫秒值之后lastTimestamp * 当某一个毫秒,序列号用完了之后,等待到下一个毫秒,在进行序列号的使用 * * @return */ private long getNexMill() { long timestamp = this.getNowTimestamp(); //不断的遍历,直到获取到lastTimestamp下一个毫秒值 while (timestamp <= lastTimestamp) { //进行时间回拨 timestamp = this.getNowTimestamp(); } return timestamp; } //获取当前毫秒值 private long getNowTimestamp() { return System.currentTimeMillis(); } /** * 使用当前计算机的MAC生成数据中心标识ID * * @param maxDataCenterId * @return */ private static long getDataCenterId(long maxDataCenterId) { long id = 0L; try { InetAddress ip = InetAddress.getLocalHost(); NetworkInterface network = NetworkInterface.getByInetAddress(ip); if (network == null) { id = 1L; } else { byte[] mac = network.getHardwareAddress(); if (mac != null) { id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; id = id % (maxDataCenterId + 1); } } } catch (Exception e) { e.printStackTrace(); } return id; } //根据当前计算机的进程PID生成机器识别ID private static long getMachineId(long dataCenterId, long maxMachineId) { StringBuilder sb = new StringBuilder(); sb.append(dataCenterId); //获取JVM进程的PID String name = ManagementFactory.getRuntimeMXBean().getName(); if (name != null) { sb.append(name.split("@")[0]); } /** * MAC+PID 的hashcode 获取16个低位 */ int id = sb.toString().hashCode() & 0xffff; return id % (maxMachineId + 1); } public Snowflake() { dataCenterId = getDataCenterId(MAX_DATA_CENTER_ID); machineId = getMachineId(dataCenterId, MAX_MACHINE_ID); } //public static void main(String[] args) { // //指定数据中心和机器识别id // Snowflake snowflake = new Snowflake(2, 3); // System.out.println("指定数据中心和机器识别ID来生成ID"); // for (int i = 0; i < 10; i++) { // System.out.println(snowflake.nextId()); // } // // //默认快速使用方式 // snowflake = new Snowflake(); // System.out.println("快速使用方式来生成ID"); // for (int i = 0; i < 10; i++) { // System.out.println(snowflake.nextId()); // } //}}
推荐阅读
- 第五人格或许可以找鹤翁帮忙怎么做
- Number,String类型 第一百零八篇:最常用的基本数据类型
- 第五人格给鹤翁盛水任务完成攻略
- 第五人格或许可以找鹤翁帮忙位置图示
- -第五人格鹤翁盛水方法攻略
- 第五人格鹤翁位置在哪
- 第五人格试着寻找长明灯怎么完成
- 王者荣耀炮火千金探索第4阶段正确答案参考-王者荣耀炮火千金探索第四阶段答案攻略
- 王者荣耀炮火千金探索第3阶段通关答案攻略-王者荣耀炮火千金探索第三阶段怎么过
- 王者荣耀炮火千金探索第2阶段答案图文攻略-王者荣耀炮火千金探索第二阶段怎么玩