首页 经验

分布式id生成器怎么实现

时间: 2024-10-21 11:11:27

(部分内容来自网络,其真实性存疑,为了避免对您造成误导,请谨慎甄别。)

在分布式系统中,生成唯一 ID 是一项重要且复杂的需求,通常有多种实现方式,每种方式都有其优缺点。以下是一些常见的分布式 ID 生成器及其实现方式。


1. UUID (通用唯一标识符)


实现方式:

- 使用 Java 提供的 java.util.UUID 类生成 UUID。UUID 是 128 位的,通常以 32 位十六进制数表示,提供较高的唯一性。


优点:

- 简单易用,易于在任何地方生成。

- 几乎不需要配置。


缺点:

- UUID 不适合用作数据库主键,存储空间较大且不具可读性(使用字符串的情况下)。

- 生成速度较慢。


示例代码:

java

import java.util.UUID;


public class UUIDGenerator {

    public static String generateId() {

        return UUID.randomUUID().toString();

    }

}


2. 雪花算法 (Snowflake)


实现方式:

- Twitter 提出的雪花算法生成 64 位唯一 ID,结构包含时间戳、工作机器 ID 和序列号。


ID 结构:

- 1 bit (标记位)

- 41 bits (时间戳,毫秒级,支持 69 年)

- 10 bits (机器 ID,支持 1024 个节点)

- 12 bits (序列号,支持同一毫秒内生成 4096 个 ID)


优点:

- 高性能;支持高并发且生成速度极快。

- 时间有序,有助于在数据库中进行排序。


缺点:

- 机器 ID 的分配与管理需要协调。

- 时间回调问题。如果系统时间发生回调,会导致 ID 冲突。


示例代码:

java

public class SnowflakeGenerator {

    private final long epoch = 1546300800000L; // 自定义起始时间

    private final long workerIdBits = 5L; // 5位机器ID

    private final long datacenterIdBits = 5L; // 5位数据中心ID

    private final long sequenceBits = 12L; // 12位序列号


    private final long maxWorkerId = -1L ^ (-1L << workerIdBits); // 31

    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 31

    private final long sequenceMask = -1L ^ (-1L << sequenceBits); // 4095


    private long workerId;

    private long datacenterId;

    private long sequence = 0L;

    private long lastTimestamp = -1L;


    // 构造函数,初始化机器 ID 和数据中心 ID

    public SnowflakeGenerator(long workerId, long datacenterId) {

        if (workerId > maxWorkerId || workerId < 0) {

            throw new IllegalArgumentException("worker Id can't be greater than " + maxWorkerId + " or less than 0");

        }

        if (datacenterId > maxDatacenterId || datacenterId < 0) {

            throw new IllegalArgumentException("datacenter Id can't be greater than " + maxDatacenterId + " or less than 0");

        }

        this.workerId = workerId;

        this.datacenterId = datacenterId;

    }


    // 生成唯一ID

    public synchronized long nextId() {

        long timestamp = System.currentTimeMillis();


        if (timestamp < lastTimestamp) {

            throw new RuntimeException("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds");

        }


        if (lastTimestamp == timestamp) {

            sequence = (sequence + 1) & sequenceMask; // 同一毫秒内生成ID++

            if (sequence == 0) {

                timestamp = tilNextMillis(lastTimestamp); // 等待下一毫秒

            }

        } else {

            sequence = 0; // 时间戳改变,序列重置

        }


        lastTimestamp = timestamp;


        return ((timestamp - epoch) << (workerIdBits + datacenterIdBits + sequenceBits)) // 时间戳部分

                | (datacenterId << (workerIdBits + sequenceBits)) // 数据中心部分

                | (workerId << sequenceBits) // 机器ID部分

                | sequence; // 序列号部分

    }


    private long tilNextMillis(long lastTimestamp) {

        long timestamp = System.currentTimeMillis();

        while (timestamp <= lastTimestamp) {

            timestamp = System.currentTimeMillis();

        }

        return timestamp;

    }

}


3. 数据库自增 ID


实现方式:

- 使用关系型数据库的自增字段生成 ID。


优点:

- 生成简单且保证唯一性。

- ID 由数据库管理,易于整合到 CRUD 操作中。


缺点:

- 性能瓶颈;高并发场景下,可能导致 ID 争用。

- 不适用于分布式架构,增加了数据库负担。


4. Redis / Zookeeper


实现方式:

- 利用 Redis 的自增特性或 Zookeeper 的节点生成器生成 ID。


优点:

- 适合在分布式环境中生成唯一 ID。

- 高性能与高可用性。


缺点:

- 需要额外的存储系统,带来一定的复杂性。


使用 Redis 示例:

java

import redis.clients.jedis.Jedis;


public class RedisIdGenerator {

    private Jedis jedis;


    public RedisIdGenerator() {

        this.jedis = new Jedis("localhost"); // 请根据需要配置

    }


    public long generateId() {

        return jedis.incr("id"); // 将 id 的值递增并返回

    }

}


总结


选择合适的分布式 ID 生成方案需要考虑多种因素,包括请求并发量、生成速度、唯一性、可读性、实现复杂性等。常用的方法包括 UUID、雪花算法、数据库自增 ID 和使用外部存储服务如 Redis 和 Zookeeper。在大型分布式系统中,雪花算法是一种广泛使用的选择,因为它能够在高并发的情况下生成有序且唯一的 ID。


上一个 JAVA 对于单例模式,有什么使用场景了,讲了全局id生成器 文章列表 下一个 Zookeeper是分布式系统中非常重要的组件,ZAB协议是其核心机制之一

最新

工具

© 2019-至今 适观科技

沪ICP备17002269号