分布式ID生成:雪花算法与UUID
分布式ID生成:雪花算法与UUID
概述
分布式ID生成是分布式系统中的重要问题。本教程介绍雪花算法和UUID的使用。
1. UUID
import java.util.UUID;
public class UUIDExample {
public static void main(String[] args) {
// 生成UUID
UUID uuid = UUID.randomUUID();
System.out.println("UUID: " + uuid.toString());
System.out.println("去除横线: " + uuid.toString().replace("-", ""));
// UUID版本
System.out.println("版本: " + uuid.version());
System.out.println("变体: " + uuid.variant());
}
}
2. 雪花算法
public class SnowflakeIdGenerator {
private final long epoch = 1609459200000L; // 起始时间戳
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
private final long sequenceBits = 12L;
private final long maxWorkerId = (1L << workerIdBits) - 1;
private final long maxDatacenterId = (1L << datacenterIdBits) - 1;
private final long sequenceMask = (1L << sequenceBits) - 1;
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private long workerId;
private long datacenterId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public SnowflakeIdGenerator(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException("Worker ID无效");
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException("Datacenter ID无效");
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
throw new RuntimeException("时钟回拨");
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - epoch) << timestampLeftShift) |
(datacenterId << datacenterIdShift) |
(workerId << workerIdShift) |
sequence;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
public static void main(String[] args) {
SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1, 1);
for (int i = 0; i < 10; i++) {
System.out.println("ID: " + generator.nextId());
}
}
}
3. 实际应用示例
分布式订单ID
@Service
public class OrderIdGenerator {
private final SnowflakeIdGenerator generator;
public OrderIdGenerator() {
this.generator = new SnowflakeIdGenerator(1, 1);
}
public String generateOrderId() {
long id = generator.nextId();
return "ORD" + id;
}
}
数据库自增ID
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@Service
public class DatabaseIdGenerator {
private final JdbcTemplate jdbcTemplate;
public long generateId(String tableName) {
String sql = "SELECT auto_increment FROM information_schema.tables WHERE table_name = ?";
Long currentId = jdbcTemplate.queryForObject(sql, Long.class, tableName);
// 更新自增ID
String updateSql = "ALTER TABLE " + tableName + " AUTO_INCREMENT = ?";
jdbcTemplate.update(updateSql, currentId + 1);
return currentId;
}
}
4. 最佳实践
- 选择合适的方案:UUID简单,雪花算法有序
- 考虑性能:雪花算法性能更高
- 处理时钟回拨:雪花算法需要处理时钟回拨问题
- 保证唯一性:确保ID在分布式环境中的唯一性
- 监控ID生成:监控ID生成速率和状态
总结
分布式ID生成是分布式系统中的重要问题。掌握UUID和雪花算法的使用,可以解决分布式系统中的ID生成问题。