用雪花算法生成全局唯一序列

雪花算法是一种分布式唯一ID生成算法,通过对时间戳、工作节点ID和序列号进行位运算和组合,生成一个可排序且唯一的64位ID。

实现原理:

  1. 首先,我们需要定义算法中的参数:

    • 时间戳:使用当前时间戳,精确到毫秒级别。
    • 工作节点ID:用于区分不同的工作节点,保证在分布式环境下生成的ID是唯一的。
    • 序列号:每个工作节点上每毫秒生成的序列号,用于解决并发生成ID时的顺序性问题。
  2. 在算法中,我们使用一个64位的long型变量来表示生成的唯一ID。其结构如下所示:

    • 第1位:固定为0,保证生成的ID为正数。
    • 第2至42位:表示时间戳,共41位,可表示2^41-1个毫秒值,大约69年的时间。
    • 第43至47位:表示工作节点ID,共5位,可表示最多32个不同的工作节点。
    • 第48至63位:表示序列号,共16位,可表示最多2^16-1个不同的序列号。
  3. 在生成唯一ID的过程中,需要注意以下几点:

    • 获取当前时间戳,并与上一次生成ID的时间戳进行比较,防止时间回拨导致生成重复ID。
    • 对并发生成ID的情况,需要通过序列号来保证生成的ID的顺序性并避免冲突。
    • 如果当前时间戳与上一次生成ID的时间戳相同,则需要增加序列号并重新计算时间戳,直到下一毫秒开始。
  4. 最后,将时间戳、工作节点ID和序列号进行位运算和组合,生成最终的唯一ID。生成ID的过程可以保证在相同毫秒内、相同工作节点和序列号的情况下生成的ID是唯一的。

通过以上原理,雪花算法可以在分布式环境中生成大量唯一ID,并且保证ID的有序性和唯一性。在实际应用中,可以根据具体需求调整参数的位数,以满足不同场景下对ID的要求。

使用Java实现雪花算法生成16位数字的代码:

public class SnowflakeAlgorithm {
    private long sequence = 0L;
    private long lastTimestamp = -1L;
    private final long workerIdBits = 5L;
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private final long sequenceBits = 10L;
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
    private final long workerIdShift = sequenceBits;
    private final long timestampLeftShift = sequenceBits + workerIdBits;
    private final long twepoch = 1622505600000L;

    private final long workerId;

    public SnowflakeAlgorithm(long workerId) {
        if (workerId < 0 || workerId > maxWorkerId) {
            throw new IllegalArgumentException("Worker ID must be between 0 and " + maxWorkerId);
        }
        this.workerId = workerId;
    }

    public synchronized long nextId() {
        long timestamp = timeGen();

        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds.");
        }

        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        return ((timestamp - twepoch) << timestampLeftShift) |
                (workerId << workerIdShift) |
                sequence;
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }
}

public class Main {
    public static void main(String[] args) {
        SnowflakeAlgorithm snowflake = new SnowflakeAlgorithm(1);

        for (int i = 0; i < 10; i++) {
            long id = snowflake.nextId();
            System.out.println(id);
        }
    }
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小云很优秀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值