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

Java阿木 发布于 19 天前 4 次阅读


智慧分布式ID生成:雪花算法、号段模式与Java实现

在分布式系统中,ID的生成是一个关键问题。一个高效、唯一且全局一致的ID生成策略对于系统的稳定性和扩展性至关重要。本文将围绕Java语言,探讨雪花算法、号段模式以及如何在Java中实现这些ID生成策略。

随着互联网的快速发展,分布式系统已经成为企业架构的重要组成部分。在分布式系统中,每个节点都需要生成唯一的ID,以标识系统中的各种实体,如用户、订单、日志等。传统的ID生成方式,如自增ID、UUID等,在分布式环境下存在诸多问题,如ID冲突、性能瓶颈等。设计一种高效、唯一且全局一致的ID生成策略变得尤为重要。

雪花算法

雪花算法(Snowflake Algorithm)是一种基于时间戳的分布式ID生成算法,由Twitter公司开源。雪花算法能够保证ID的唯一性、有序性和高效性。

雪花算法原理

雪花算法将一个64位的长整型数字分为5个部分:

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

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

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

4. 序列号(12位):表示同一毫秒内生成的ID序列号,用于解决同一毫秒内多个ID生成请求的问题。

雪花算法Java实现

java

public class SnowflakeIdWorker {


private long twepoch = 1288834974657L;


private long datacenterIdBits = 5L;


private long machineIdBits = 5L;


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


private long maxMachineId = -1L ^ (-1L << machineIdBits);


private long sequenceBits = 12L;

private long datacenterId = 0L;


private long machineId = 0L;


private long sequence = 0L;

private long lastTimestamp = -1L;

public SnowflakeIdWorker(long datacenterId, long machineId) {


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


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


}


if (machineId > maxMachineId || machineId < 0) {


throw new IllegalArgumentException(String.format("Machine ID can't be greater than %d or less than 0", maxMachineId));


}


this.datacenterId = datacenterId;


this.machineId = machineId;


}

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) & 0xFFF;


if (sequence == 0) {


timestamp = tilNextMillis(lastTimestamp);


}


} else {


sequence = 0L;


}

lastTimestamp = timestamp;

return ((timestamp - twepoch) << sequenceBits) | (datacenterId << (sequenceBits + datacenterIdBits)) | (machineId << (sequenceBits + datacenterIdBits + machineIdBits)) | 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生成。

号段模式原理

1. 预分配ID范围:根据业务需求,将ID范围划分为多个号段,每个号段对应一个业务模块或服务。

2. 分配号段:将号段分配给相应的业务模块或服务。

3. 生成ID:业务模块或服务从分配的号段中获取ID。

号段模式Java实现

java

public class SegmentIdGenerator {


private final long start;


private final long end;


private long current = -1L;

public SegmentIdGenerator(long start, long end) {


this.start = start;


this.end = end;


}

public synchronized long nextId() {


if (current == -1L) {


current = start;


}


if (current > end) {


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


}


return current++;


}


}


总结

本文介绍了雪花算法和号段模式两种分布式ID生成策略,并展示了如何在Java中实现它们。雪花算法能够保证ID的唯一性、有序性和高效性,而号段模式则能够实现高效、有序的ID生成。在实际应用中,可以根据业务需求选择合适的ID生成策略,以提高系统的稳定性和扩展性。