JAVA---雪花算法(Snowflake)实现

雪花算法(Snowflake)是Twitter开源的一种分布式唯一ID生成算法,用于在分布式系统中生成全局唯一的ID。雪花算法生成的ID是一个64位的整数,通常表示为长整型(long)。

雪花算法的结构

雪花算法生成的ID由以下几部分组成:

  1. 符号位(1位):始终为0,保证生成的ID为正数。
  2. 时间戳(41位):记录生成ID的时间戳,精确到毫秒级。可以使用大约69年的时间。
  3. 机器ID(10位):标识生成ID的机器,可以支持1024台机器。
  4. 序列号(12位):同一毫秒内生成的多个ID的序列号,可以支持每毫秒生成4096个ID。

实现原理

  1. 时间戳

    • 使用当前时间戳减去一个固定的起始时间戳(通常是系统启动时间或一个固定的过去时间),得到一个相对时间戳。
    • 41位的时间戳可以表示的最大值是2^41 - 1,大约是69年。
  2. 机器ID

    • 每个生成ID的机器都有一个唯一的机器ID,通常由数据中心ID和机器ID组成,共10位,可以支持1024台机器。
  3. 序列号

    • 在同一毫秒内,如果生成的ID数量超过4096个,则需要等待下一毫秒再生成新的ID。
    • 序列号从0开始递增,每生成一个ID,序列号加1,直到达到4095,然后重置为0。

生成ID的步骤

  1. 获取当前时间戳

    • 获取当前系统时间戳(毫秒级),减去起始时间戳,得到相对时间戳。
  2. 检查时间戳是否发生变化

    • 如果当前时间戳与上一次生成ID的时间戳相同,则序列号加1。
    • 如果序列号达到4095,则等待下一毫秒再生成新的ID。
  3. 组装ID

    • 将符号位、时间戳、机器ID和序列号按位拼接,生成最终的64位ID。

示例代码

以下是一个简单的雪花算法实现示例:

public class SnowflakeIdGenerator {
    private final long twepoch = 1288834974657L; // 起始时间戳,例如Twitter的Snowflake起始时间
    private final long workerIdBits = 10L;
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private final long sequenceBits = 12L;
    private final long workerIdShift = sequenceBits;
    private final long timestampLeftShift = sequenceBits + workerIdBits;
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    private long workerId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeIdGenerator(long workerId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        this.workerId = workerId;
    }

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

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

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

        lastTimestamp = timestamp;

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

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

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

    public static void main(String[] args) {
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1);
        System.out.println(idGenerator.nextId());
    }
}

总结

雪花算法通过组合时间戳、机器ID和序列号,生成全局唯一的64位ID。这种算法简单高效,适用于分布式系统中唯一ID的生成需求。通过合理配置机器ID和起始时间戳,可以满足不同规模和需求的系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

需要重新演唱

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

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

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

打赏作者

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

抵扣说明:

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

余额充值