实现分布式系统ID的生成算法可以使用Snowflake算法

Snowflake算法是Twitter开源的分布式ID生成算法,它可以生成唯一的64位ID,其中包含了时间戳、机器ID和序列号。下面是使用Java语言实现Snowflake算法的代码:

public class SnowflakeIdWorker {
    
    public static void main(String[] args) {
        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1L);
        // 生成10个ID 
        for (int i = 0; i < 10; i++) { 
            long id = idWorker.nextId();
            System.out.println(id);
        } 
    }
    

    // 时间戳占用的位数
        
    private static final long TIMESTAMP_BITS = 41L;
    
    // 机器ID占用的位数
    
    private static final long WORKER_ID_BITS = 10L;
    
    // 序列号占用的位数
    private static final long SEQUENCE_BITS = 12L;
    
    // 最大的机器ID,1023
    private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
    
    // 最大的序列号,4095
    private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);
    
    // 时间戳的左移位数,22
    private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
    
    // 机器ID的左移位数,12
    private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
    
    // 上次生成ID的时间戳
    private long lastTimestamp = -1L;
    
    // 序列号
    private long sequence = 0L;
    
    // 机器ID
    private final long workerId;
    
    // 构造函数
    public SnowflakeIdWorker(long workerId) {
    if (workerId < 0 || workerId > MAX_WORKER_ID) {
    throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", MAX_WORKER_ID));
    }
    this.workerId = workerId;
    }
    
    // 生成ID的方法
    public synchronized long nextId() {
    long timestamp = System.currentTimeMillis();
    
    // 如果当前时间小于上次生成ID的时间戳,则说明系统时钟回退过,需要等待时间追上上次的时间戳
    if (timestamp < lastTimestamp) {
    try {
    wait(lastTimestamp - timestamp);
    } catch (InterruptedException e) {
    throw new RuntimeException(e);
    }
    timestamp = System.currentTimeMillis();
    if (timestamp < lastTimestamp) {
    throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
    }
    }
    
    // 如果是同一时间生成的,则需要使用序列号来区分不同的ID
    if (lastTimestamp == timestamp) {
    sequence = (sequence + 1) & MAX_SEQUENCE;
    if (sequence == 0) {
    timestamp = tilNextMillis(lastTimestamp);
    }
    } else {
    sequence = 0L;
    }
    
    lastTimestamp = timestamp;
    
    // ID格式为:时间戳-机器ID-序列号
    return ((timestamp << TIMESTAMP_SHIFT) | (workerId << WORKER_ID_SHIFT) | sequence);
    }
    
    // 等待时间追上上次的时间戳
    private long tilNextMillis(long lastTimestamp) {
    long timestamp = System.currentTimeMillis();
    while (timestamp <= lastTimestamp) {
    timestamp = System.currentTimeMillis();
    }
    return timestamp;
    }


}


上述代码中,使用SnowflakeIdWorker类生成了10个分布式ID。在构造函数中指定机器ID,调用nextId方法可以生成一个唯一的ID。这个ID由三个部分组成:时间戳、机器ID和序列号。其中时间戳占用了41位,可以支持69年的时间戳;机器ID占用了10位,可以支持1024台机器;序列号占用了12位,可以在同一毫秒内生成4096个ID。生成的ID是一个64位的long类型数据,可以在分布式系统中唯一标识一个对象。
 

猜你喜欢

转载自blog.csdn.net/yijiemuhuashi/article/details/129766829