生成唯一的ID
在Java开发中,我们经常会遇到需要生成唯一的ID的情况,比如数据库中的主键、分布式系统中的事务ID等。本文将介绍几种生成唯一ID的常用方法,并提供相应的代码示例。
UUID
UUID(Universally Unique Identifier)是一个标准的32位长度的字符串,它可以用来生成唯一的ID。Java中可以使用java.util.UUID类来生成UUID。
import java.util.UUID;
public class UUIDExample {
public static void main(String[] args) {
UUID uuid = UUID.randomUUID();
System.out.println(uuid.toString());
}
}
上述代码会输出一个类似于550e8400-e29b-41d4-a716-446655440000的字符串,这就是一个UUID。UUID的生成是基于当前时间、计算机的硬件地址和其他唯一的标识符来实现的,基本上可以保证生成的ID是唯一的。但是UUID的长度较长,不适合作为数据库的主键。
自增ID
自增ID是指一个递增的整数,可以通过数据库的自增主键来实现。在Java中,可以使用数据库的自增主键来生成唯一的ID。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class AutoIncrementIDExample {
public static void main(String[] args) {
try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "username", "password");
Statement stmt = conn.createStatement();
String sql = "INSERT INTO users (name) VALUES ('John')";
stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()) {
int id = rs.getInt(1);
System.out.println(id);
}
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
上述代码通过JDBC连接到数据库,并执行一条插入语句,获取自增主键的值作为唯一ID。这种方法在分布式系统中不适用,因为每个节点都需要连接到数据库来生成ID,可能会引起性能问题。
雪花算法
雪花算法(Snowflake)是Twitter开源的一种生成唯一ID的算法,它可以在分布式系统中生成有序的、唯一的ID。雪花算法的ID是一个64位的整数,由以下几部分组成:
- 时间戳(41位):精确到毫秒级别的时间戳,可以使用当前时间减去一个起始时间戳来得到相对时间,可以使用System.currentTimeMillis()来获取当前时间戳。
- 机器ID(10位):机器的唯一标识符,可以通过将机器的IP地址转换为一个数字来得到。
- 序列号(12位):同一毫秒内生成的ID的序列号,从0开始递增,如果同一毫秒生成的ID数量超过4096,可以等待下一毫秒再继续生成。
下面是一个使用雪花算法生成唯一ID的示例代码:
public class SnowflakeIDExample {
private static final long START_TIMESTAMP = 1635148800000L;
private static final long WORKER_ID_BITS = 10L;
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
private static final long SEQUENCE_BITS = 12L;
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
private long workerId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public SnowflakeIDExample(long workerId) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException(String.format("Worker ID can't be greater than %d or less than 0", MAX_WORKER_ID));
}
this.workerId = workerId;
}
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate ID");
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & SEQUENCE_MASK;
if (sequence ==
















