掌握Java流水号生成,告别重复编号烦恼

掌握Java流水号生成,告别重复编号烦恼

流水号生成是许多业务系统中常见的需求,它用于为每个记录生成一个唯一的标识符。在Java中,实现流水号生成有多种方法,以下将详细介绍几种常见的流水号生成策略,帮助您告别重复编号的烦恼。

1. 数据库自增主键

最简单的方式是利用数据库自增主键生成流水号。大多数关系型数据库都支持自增字段,每次插入新记录时,数据库会自动为该字段分配一个递增的值。

1.1 MySQL实现

以下是一个简单的MySQL示例:

CREATE TABLE `test` (

`id` INT NOT NULL AUTO_INCREMENT,

`data` VARCHAR(255) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `test` (`data`) VALUES ('example data');

1.2 Oracle实现

Oracle数据库中,可以使用序列(Sequence)来生成流水号:

CREATE SEQUENCE seq_test

START WITH 1

INCREMENT BY 1

NOCACHE

NOCYCLE;

INSERT INTO `test` (`data`) VALUES ('example data');

2. Snowflake算法

Snowflake算法是一种分布式系统中常用的高效唯一ID生成算法。它能够生成64位的长整型ID,其中包含时间戳、数据中心ID、机器ID和序列号。

2.1 Snowflake算法原理

41位时间戳:表示毫秒级的时间戳,精确到毫秒。

10位数据中心ID:表示数据中心ID,用于区分不同数据中心。

5位机器ID:表示机器ID,用于区分同一数据中心下的不同机器。

12位序列号:表示同一毫秒内生成的ID序列,范围是0到4095。

2.2 Java实现

以下是一个简单的Java实现:

public class SnowflakeIdWorker {

private long workerId;

private long datacenterId;

private long sequence = 0L;

private long twepoch = 1288834974657L;

private long workerIdBits = 5L;

private long datacenterIdBits = 5L;

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

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

private long sequenceBits = 12L;

private long workerIdShift = sequenceBits;

private long datacenterIdShift = sequenceBits + workerIdBits;

private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

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

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();

}

}

3. UUID生成

UUID(通用唯一识别码)是一种128位的数字,可以保证在全球范围内唯一。Java中可以使用java.util.UUID类生成UUID。

3.1 Java实现

以下是一个简单的Java示例:

import java.util.UUID;

public class UUIDGenerator {

public static void main(String[] args) {

UUID uuid = UUID.randomUUID();

System.out.println(uuid.toString());

}

}

总结

本文介绍了三种常见的Java流水号生成方法:数据库自增主键、Snowflake算法和UUID生成。根据实际需求选择合适的方法,可以有效地解决重复编号的烦恼。在实际应用中,可以根据业务场景和性能要求进行优化和调整。

相关创作