雪花算法,在分布式环境下实现高效的ID生成

其实雪花算法比较简单,可能称不上什么算法就是一种构造UID的方法。

点1:UID是一个long类型的41位时间戳,10位存储机器码,12位存储序列号。

点2:时间戳的单位是毫秒,可以同时链接1024台机器,每台机器每毫秒可以使用4096个序列好,我们会给生成id上一个同步锁,阻塞住其他线程的访问。

点3:利用掩码我们可以检测序列是否溢出,如果溢出的话,就强制等待到下一毫秒。

java 复制代码
/**
 * @author hardstone
 * @since 29 July 2023(1690603385473)
 */
public class SnowFlakes {
    //开始的时间戳
    private final  long start = 1690603385473L;
    //机器标识长度5位
    private final long machineIdBits = 5L;
    //机器集群标识长度5位
    private final long centerIdBits = 5L;
    //序列标识所占位数12位
    private final long sequenceBits = 12L;
    //机器标识最大值
    private final long maxMachineId = -1L ^ (-1L << machineIdBits);
    //机器集群标识最大值
    private final long maxCenterId = -1L ^ (-1L << centerIdBits);
    //序列标识的最大值
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
    //机器标识左移长度
    private final long machineIdShift = sequenceBits;
    //机器集群标识左移长度
    private final long centerIdShift = sequenceBits + machineIdBits;
    //时间戳左移长度
    private final long timeStampIdShift = sequenceBits + machineIdBits + centerIdBits;
    //序列Id
    private long sequence = 0L;

    //机器Id
    private long machineId;

    //机器集群Id
    private long centerId;

    //时间戳
    private long lastTimeStamp = -1L;

    public SnowFlakes(long machineId, long centerId) {
        if (machineId > maxMachineId || machineId < 0) {
            throw new IllegalArgumentException(String.format("WorkerId should be between 0 and 31"));
        }
        if (centerId > maxCenterId || centerId < 0) {
            throw new IllegalArgumentException(String.format("CenterId should be between 0 and 31"));
        }
    }
    public synchronized long nextId() {
        long timeStamp = System.currentTimeMillis();
        //时间回滚现象
        if (timeStamp < lastTimeStamp) {
            throw new RuntimeException(
                    String.format("Time gone backwards!")
            );
        }
        if (lastTimeStamp == timeStamp) {
            sequence = (sequence + 1) & sequenceMask;
            //如果序列分配完了
            if (sequence == 0) {
                timeStamp = getNextMillis(lastTimeStamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimeStamp = timeStamp;
        return ((timeStamp - start) << timeStampIdShift)
                | (centerId << centerIdShift)
                | (machineId << machineIdShift)
                | sequence;
    }
    protected long getNextMillis(long lastTimeStamp) {
        long timeStamp = System.currentTimeMillis();
        while (timeStamp <= lastTimeStamp) {
            timeStamp = System.currentTimeMillis();
        }
        return timeStamp;
    }
    public static void main(String[] args) {
        System.out.println(new SnowFlakes(0, 0).nextId());
    }
}
相关推荐
Miraitowa_cheems21 分钟前
LeetCode算法日记 - Day 11: 寻找峰值、山脉数组的峰顶索引
java·算法·leetcode
CoovallyAIHub43 分钟前
方案 | 动车底部零部件检测实时流水线检测算法改进
深度学习·算法·计算机视觉
CoovallyAIHub1 小时前
方案 | 光伏清洁机器人系统详细技术实施方案
深度学习·算法·计算机视觉
lxmyzzs1 小时前
【图像算法 - 14】精准识别路面墙体裂缝:基于YOLO12与OpenCV的实例分割智能检测实战(附完整代码)
人工智能·opencv·算法·计算机视觉·裂缝检测·yolo12
洋曼巴-young1 小时前
240. 搜索二维矩阵 II
数据结构·算法·矩阵
楼田莉子2 小时前
C++算法题目分享:二叉搜索树相关的习题
数据结构·c++·学习·算法·leetcode·面试
pusue_the_sun3 小时前
数据结构——栈和队列oj练习
c语言·数据结构·算法··队列
大锦终3 小时前
【算法】模拟专题
c++·算法
Xの哲學4 小时前
Perf使用详解
linux·网络·网络协议·算法·架构
想不明白的过度思考者4 小时前
数据结构(排序篇)——七大排序算法奇幻之旅:从扑克牌到百亿数据的魔法整理术
数据结构·算法·排序算法