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

CSDN 2024-09-13 11:35:01 阅读 96

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

雪花算法的结构

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

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

实现原理

时间戳

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

机器ID

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

序列号

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

生成ID的步骤

获取当前时间戳

获取当前系统时间戳(毫秒级),减去起始时间戳,得到相对时间戳。

检查时间戳是否发生变化

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

组装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和起始时间戳,可以满足不同规模和需求的系统。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。