返回

分布式ID:互联网巨头是如何解决的?

数据库

应对海量并发:分布式ID方案详解

随着互联网的爆炸式增长,用户数量和数据体量急剧攀升,对唯一ID的需求也随之激增。然而,传统的主键自增ID方案已难以满足海量并发的性能和可扩展性要求。分布式ID方案应运而生,为互联网巨头解决这一难题提供了有效手段。

什么是分布式ID?

分布式ID是一种在分布式系统中生成全局唯一ID的技术。它不同于传统的主键自增ID,而是通过分散式机制,在不同节点上独立生成ID,从而应对海量并发场景下的性能瓶颈。

分布式ID方案分类

根据生成方式,分布式ID方案可分为以下几类:

  • 数据库自增ID: 由数据库系统自动生成ID。
  • 算法生成ID: 根据特定算法生成ID,如雪花算法和UUID。
  • 外部服务生成ID: 通过调用外部服务(如Segment)来生成ID。

分布式ID方案详解

数据库自增ID

这种方案最简单,由数据库创建自增ID表,通过数据库的自增机制生成ID。优点是实现简单,性能较好。但缺点是扩展性差,当并发量较大时会出现性能瓶颈。

算法生成ID

雪花算法是一种广泛使用的算法生成ID方案。它将ID分为三部分:时间戳、机器ID和序列号。时间戳记录ID生成的当前时间,机器ID记录ID生成所在的机器ID,序列号记录自上次生成ID以来的序号。雪花算法的优点是生成速度快,但缺点是需要维护机器ID,且时间戳的精度会影响ID的唯一性。

UUID

UUID(通用唯一标识符)是一种128位的随机生成ID,由一系列十六进制数字组成。它具有全局唯一性,不需要依赖任何外部系统。UUID的优点是随机性高,缺点是生成速度慢,且ID长度较长,不利于存储和传输。

Segment

Segment是一种基于Twitter开源的Snowflake算法实现的ID生成服务。它提供了RESTful API和客户端SDK,可以方便地生成ID。Segment的优点是易于使用,可扩展性好,但缺点是需要依赖外部服务,可能会产生额外的延迟。

不同方案对比

方案 优点 缺点
数据库自增ID 实现简单,性能较好 扩展性差
雪花算法 生成速度快 需要维护机器ID,时间戳精度影响唯一性
UUID 全局唯一性高 生成速度慢,ID长度较长
Segment 易于使用,可扩展性好 需要依赖外部服务

选型建议

根据不同的业务场景,应选择合适的分布式ID方案:

  • 并发量较低,对性能要求不高:可以使用数据库自增ID方案。
  • 并发量较大,对性能要求较高:可以使用雪花算法或Segment方案。
  • 需要全局唯一性,对性能要求不高:可以使用UUID方案。

代码示例

雪花算法

public class SnowflakeIdGenerator {
    private static final long EPOCH = 1420070400000L; // 起始时间戳,2015-01-01 00:00:00
    private static final long DATA_CENTER_ID_BITS = 5L; // 数据中心ID长度,最多可以支持32个数据中心
    private static final long WORKER_ID_BITS = 5L; // 机器ID长度,最多可以支持32台机器
    private static final long SEQUENCE_BITS = 12L; // 序列号长度,最多可以生成4096个序列号
    private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS;
    private static final long WORKER_ID_SHIFT = SEQUENCE_BITS + DATA_CENTER_ID_BITS;
    private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + DATA_CENTER_ID_BITS + WORKER_ID_BITS;
    private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
    private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
    private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);

    private long dataCenterId; // 数据中心ID
    private long workerId; // 机器ID
    private long sequence; // 序列号
    private long lastTimestamp = -1L; // 上次生成ID的时间戳

    public SnowflakeIdGenerator(long dataCenterId, long workerId) {
        if (dataCenterId < 0 || dataCenterId > MAX_DATA_CENTER_ID) {
            throw new IllegalArgumentException("Data center ID must be between 0 and " + MAX_DATA_CENTER_ID);
        }
        if (workerId < 0 || workerId > MAX_WORKER_ID) {
            throw new IllegalArgumentException("Worker ID must be between 0 and " + MAX_WORKER_ID);
        }
        this.dataCenterId = dataCenterId;
        this.workerId = workerId;
    }

    public synchronized long nextId() {
        long timestamp = System.currentTimeMillis();
        if (timestamp < lastTimestamp) {
            throw new IllegalStateException("Clock moved backwards.");
        }
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0;
        }
        lastTimestamp = timestamp;
        return ((timestamp - EPOCH) << TIMESTAMP_LEFT_SHIFT) | (dataCenterId << DATA_CENTER_ID_SHIFT) | (workerId << WORKER_ID_SHIFT) | sequence;
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }
}

Segment

import com.segment.analytics.Analytics;
import com.segment.analytics.messages.IdentifyMessage;
import java.util.UUID;

public class SegmentIdGenerator {
    private static final Analytics analytics = new Analytics.Builder("YOUR_WRITE_KEY").build();

    public static String nextId() {
        IdentifyMessage message = new IdentifyMessage()
                .userId(UUID.randomUUID().toString());
        analytics.enqueue(message);
        return message.getUserId();
    }
}

总结

分布式ID方案是互联网巨头应对海量并发场景下ID生成需求的有效手段。根据不同的业务场景,选择合适的分布式ID方案至关重要。本文详解了多种分布式ID方案,希望能够为读者在实践中提供指导。

常见问题解答

1. 分布式ID和主键自增ID有什么区别?

分布式ID在分布式系统中生成全局唯一ID,而主键自增ID由数据库自动生成ID,具有局部唯一性。

2. 雪花算法和UUID有什么区别?

雪花算法是一种算法生成ID方案,它将ID分为时间戳、机器ID和序列号,而UUID是一种随机生成ID方案,具有全局唯一性。

3. Segment是一个什么样的服务?

Segment是一种基于Twitter开源的Snowflake算法实现的ID生成服务,它提供了RESTful API和客户端SDK,可以方便地生成ID。

4. 如何选择合适的分布式ID方案?

根据不同的业务场景,应考虑并发量、性能要求和全局唯一性要求,选择合适的分布式ID方案。

5. 分布式ID方案有哪些需要注意的要点?

需要考虑机器ID的维护、时间戳精度的影响、ID长度和存储成本等因素。