18.9.3 分布式ID生成方案对比

1. 分布式ID生成方案概述

1.1 分布式ID基本要求

public class DistributedIdPrinciple {
    
    /*
     * 分布式ID基本要求:
     * 
     * 1. 全局唯一性
     *    - 在分布式环境下保证ID的唯一性
     * 
     * 2. 高性能
     *    - 生成速度快,支持高并发
     * 
     * 3. 高可用
     *    - 服务高可用,不能成为单点故障
     * 
     * 4. 趋势递增
     *    - 大致按时间递增,便于数据库索引
     * 
     * 5. 信息安全
     *    - 不能暴露业务信息,防止被猜测
     * 
     * 常见方案:
     * - UUID
     * - 数据库自增ID
     * - Redis原子操作
     * - 雪花算法(Snowflake)
     * - 美团Leaf
     * - 百度UidGenerator
     */
    
    public void demonstrateIdGenerationSchemes() {
        System.out.println("=== 分布式ID生成方案演示 ===");
        
        demonstrateUUID();
        demonstrateDatabaseIncrement();
        demonstrateRedisIncrement();
        demonstrateSnowflake();
    }
    
    private void demonstrateUUID() {
        System.out.println("--- UUID方案演示 ---");
        
        UUIDGenerator uuidGenerator = new UUIDGenerator();
        
        System.out.println("1. 生成UUID:");
        for (int i = 0; i < 5; i++) {
            String uuid = uuidGenerator.generateId();
            System.out.println("  " + uuid);
        }
        
        System.out.println("\n2. UUID特点:");
        System.out.println("  优点: 简单易用,本地生成,性能高");
        System.out.println("  缺点: 长度较长,无序,不适合数据库主键");
        System.out.println();
    }
    
    private void demonstrateDatabaseIncrement() {
        System.out.println("--- 数据库自增ID演示 ---");
        
        DatabaseIdGenerator dbGenerator = new DatabaseIdGenerator();
        
        System.out.println("1. 生成数据库自增ID:");
        for (int i = 0; i < 5; i++) {
            long id = dbGenerator.generateId();
            System.out.println("  " + id);
        }
        
        System.out.println("\n2. 数据库自增ID特点:");
        System.out.println("  优点: 简单,有序递增,适合数据库");
        System.out.println("  缺点: 单点故障,性能瓶颈,扩展困难");
        System.out.println();
    }
    
    private void demonstrateRedisIncrement() {
        System.out.println("--- Redis原子操作演示 ---");
        
        RedisIdGenerator redisGenerator = new RedisIdGenerator();
        
        System.out.println("1. 生成Redis自增ID:");
        for (int i = 0; i < 5; i++) {
            long id = redisGenerator.generateId();
            System.out.println("  " + id);
        }
        
        System.out.println("\n2. Redis自增ID特点:");
        System.out.println("  优点: 性能高,有序递增,支持集群");
        System.out.println("  缺点: 依赖Redis,可能丢失数据");
        System.out.println();
    }
    
    private void demonstrateSnowflake() {
        System.out.println("--- 雪花算法演示 ---");
        
        SnowflakeIdGenerator snowflake = new SnowflakeIdGenerator(1, 1);
        
        System.out.println("1. 生成Snowflake ID:");
        for (int i = 0; i < 5; i++) {
            long id = snowflake.generateId();
            System.out.println("  " + id + " (二进制: " + Long.toBinaryString(id) + ")");
        }
        
        System.out.println("\n2. Snowflake特点:");
        System.out.println("  优点: 高性能,趋势递增,包含时间信息");
        System.out.println("  缺点: 依赖系统时钟,时钟回拨问题");
        System.out.println();
    }
}

// UUID生成器
class UUIDGenerator {
    public String generateId() {
        return java.util.UUID.randomUUID().toString().replace("-", "");
    }
}

// 数据库自增ID生成器
class DatabaseIdGenerator {
    private long currentId = 1000;
    
    public synchronized long generateId() {
        // 模拟数据库自增操作
        try {
            Thread.sleep(1); // 模拟数据库访问延迟
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        return ++currentId;
    }
}

// Redis自增ID生成器
class RedisIdGenerator {
    private long currentId = 10000;
    
    public synchronized long generateId() {
        // 模拟Redis INCR操作
        return ++currentId;
    }
}

// 雪花算法ID生成器
class SnowflakeIdGenerator {
    // 起始时间戳 (2020-01-01)
    private final long START_TIMESTAMP = 1577836800000L;
    
    // 各部分位数
    private final long SEQUENCE_BITS = 12;
    private final long MACHINE_BITS = 5;
    private final long DATACENTER_BITS = 5;
    
    // 最大值
    private final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1;
    private final long MAX_MACHINE_NUM = (1L << MACHINE_BITS) - 1;
    private final long MAX_DATACENTER_NUM = (1L << DATACENTER_BITS) - 1;
    
    // 位移
    private final long MACHINE_LEFT = SEQUENCE_BITS;
    private final long DATACENTER_LEFT = SEQUENCE_BITS + MACHINE_BITS;
    private final long TIMESTAMP_LEFT = DATACENTER_LEFT + DATACENTER_BITS;
    
    private long datacenterId;
    private long machineId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;
    
    public SnowflakeIdGenerator(long datacenterId, long machineId) {
        if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
            throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
        }
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
        }
        this.datacenterId = datacenterId;
        this.machineId = machineId;
    }
    
    public synchronized long generateId() {
        

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java面试圣经 文章被收录于专栏

Java面试圣经,带你练透java圣经

全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务