← 返回首页
🔢

分布式ID生成:雪花算法与UUID

📂 java ⏱ 3 min 404 words

分布式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. 最佳实践

  1. 选择合适的方案:UUID简单,雪花算法有序
  2. 考虑性能:雪花算法性能更高
  3. 处理时钟回拨:雪花算法需要处理时钟回拨问题
  4. 保证唯一性:确保ID在分布式环境中的唯一性
  5. 监控ID生成:监控ID生成速率和状态

总结

分布式ID生成是分布式系统中的重要问题。掌握UUID和雪花算法的使用,可以解决分布式系统中的ID生成问题。