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类型 第一百零八篇:最常用的基本数据类型