Java 语言 Java智慧分布式ID 雪花算法号段模式生成

Java阿木 发布于 21 天前 3 次阅读


Java智慧分布式ID:雪花算法号段模式生成详解

在分布式系统中,为每个节点生成唯一且有序的ID是一个常见的需求。雪花算法(Snowflake Algorithm)是一种常用的分布式ID生成策略,它能够保证ID的唯一性、有序性和高效性。本文将围绕Java语言,详细介绍雪花算法的原理、实现以及号段模式生成。

一、雪花算法概述

雪花算法由Twitter开源,是一种基于时间戳的分布式ID生成算法。它将一个64位的长整型数字分为五个部分:

1. 时间戳(41位):表示从纪元(1970年1月1日)到当前时间的毫秒数。

2. 数据中心ID(5位):表示数据中心ID,用于区分不同数据中心。

3. 机器ID(5位):表示机器ID,用于区分同一数据中心内的不同机器。

4. 序列号(12位):表示同一毫秒内生成的ID序列号,用于保证同一毫秒内ID的有序性。

5. 机器ID左移(12位):用于生成机器ID,保证同一机器ID的有序性。

二、雪花算法实现

下面是使用Java实现雪花算法的示例代码:

java

public class SnowflakeIdWorker {


// 纪元时间戳(1970年1月1日)


private final long twepoch = 1288834974657L;

// 机器ID占用的位数


private final long workerIdBits = 5L;

// 数据中心ID占用的位数


private final long datacenterIdBits = 5L;

// 机器ID最大值


private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

// 数据中心ID最大值


private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

// 序列号占用的位数


private final long sequenceBits = 12L;

// 机器ID左移位数


private final long workerIdShift = sequenceBits;

// 数据中心ID左移位数


private final long datacenterIdShift = sequenceBits + workerIdBits;

// 时间戳左移位数


private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

// 序列号最大值


private final long sequenceMask = -1L ^ (-1L << sequenceBits);

// 上次生成ID的时间戳


private long lastTimestamp = -1L;

// 序列号


private long sequence = 0L;

// 数据中心ID


private long datacenterId;

// 机器ID


private long workerId;

public SnowflakeIdWorker(long workerId, long datacenterId) {


if (workerId > maxWorkerId || workerId < 0) {


throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));


}


if (datacenterId > maxDatacenterId || datacenterId < 0) {


throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));


}


this.workerId = workerId;


this.datacenterId = datacenterId;


}

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) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;


}

private long tilNextMillis(long lastTimestamp) {


long timestamp = timeGen();


while (timestamp <= lastTimestamp) {


timestamp = timeGen();


}


return timestamp;


}

private long timeGen() {


return System.currentTimeMillis();


}


}


三、号段模式生成

雪花算法生成的ID是全局唯一的,但有时我们还需要为特定业务生成有序的ID。这时,我们可以使用号段模式生成ID。

号段模式的核心思想是将ID空间划分为多个连续的号段,每个号段由一个起始ID和结束ID表示。当需要生成ID时,从对应的号段中取一个ID,并更新号段的起始ID。

下面是使用Java实现号段模式生成ID的示例代码:

java

public class SegmentIdGenerator {


private final long startId;


private final long endId;


private long currentId;

public SegmentIdGenerator(long startId, long endId) {


this.startId = startId;


this.endId = endId;


this.currentId = startId;


}

public synchronized long nextId() {


if (currentId > endId) {


throw new RuntimeException("No more id available");


}


return currentId++;


}


}


四、总结

本文详细介绍了Java智慧分布式ID:雪花算法号段模式生成的相关技术。雪花算法能够保证ID的唯一性、有序性和高效性,而号段模式则能够满足特定业务对有序ID的需求。在实际应用中,我们可以根据具体场景选择合适的ID生成策略。