学习整理,如有错误,欢迎指正

雪花算法

概述:

Snowflake 是 Twitter 开源的分布式 ID 生成算法。Snowflake 由 64 bit 的二进制数字组成,这 64bit 的二进制被分成了几部分,每一部分存储的数据都有特定的含义:

在这里插入图片描述

  • sign(1bit):符号位(标识正负),始终为 0,代表生成的 ID 为正数。
  • timestamp (41 bits):一共 41 位,用来表示相对时间戳(距自定义基点的毫秒数),可支撑 2^41 毫秒(约 69 年)。通常基点设为系统上线时间(如 2020-01-01),而非 Unix 纪元
  • datacenter id + worker id (10 bits):一般来说,前 5 位表示机房 ID,后 5 位表示机器 ID(实际项目中可以根据实际情况调整)。这样就可以区分不同集群/机房的节点。
  • sequence (12 bits):一共 12 位,用来表示序列号。 序列号为自增值,代表单台机器每毫秒能够产生的最大 ID 数(2^12 = 4096),也就是说单台机器每毫秒最多可以生成 4096 个 唯一 ID。

优缺点:

优点:生成速度比较快、生成的 ID 有序递增、比较灵活(可以对 Snowflake 算法进行简单的改造比如加入业务 ID)。

缺点时钟回拨风险(需额外处理,详见上方解决方案)、依赖机器 ID 对分布式环境不友好(当需要自动启停或增减机器时,固定的机器 ID 可能不够灵活)。

使用:

轻量化:hutool

糊涂包中,包含雪花算法实现

  • 优点:
    零配置、使用简单
    无需额外组件
  • 注意:
    需要自行保证 workerId 唯一
    更适合单机或小规模部署
  • 依赖(Maven):
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-core</artifactId>
    <version>5.8.26</version>
</dependency>
  • 使用示例:
// 参数:workerId(0~31)、dataCenterId(0~31)
Snowflake snowflake=IdUtil.getSnowflake(1, 1);
long id=snowflake.nextId();

稳定:美团 Leaf

美团 Leaf(Leaf‑snowflake)

  • 优点:大厂生产验证、自动分配 workerId(依赖 ZK)、完善的时钟回拨处理、支持监控告警
  • 适合:中大型分布式系统、需要严格唯一与高可用
  • 地址:https://github.com/Meituan-Dianping/Leaf

Leaf提供了两种实现方式:

号段模式(Segment)和 Snowflake 模式

segment方式:

通过从数据库批量获取一段连续ID(号段),缓存在内存中自增发号。
- 数据库只参与“号段分配”,不参与每次发号
- 内存生成ID,性能高
- 通过“双buffer预加载”机制避免号段切换时阻塞

适用场景:
- 大多数业务系统(订单、用户等)
- 对稳定性要求高但不追求完全去中心化的场景

流程:

1、添加依赖

Leaf 官方没有发布到 Maven 中央仓库

本地 install

git clone https://github.com/Meituan-Dianping/Leaf.git
cd Leaf
mvn clean install -DskipTests

执行完后,本地仓库就有了:

<dependency>
    <groupId>com.sankuai.inf.leaf</groupId>
    <artifactId>leaf-core</artifactId>
    <version>1.0.0</version>
</dependency>

随后加入maven可正常使用

2、Spring Boot 配置

application.yml中进行配置项配置

leaf:
  segment:
    enable: true
  jdbc:
    url: jdbc:mysql://localhost:3306/leaf
    username: root
    password: root

3、 初始化数据库

CREATE DATABASE leaf;

CREATE TABLE leaf_alloc (
  biz_tag varchar(128) NOT NULL,
  max_id bigint NOT NULL DEFAULT 1,
  step int NOT NULL,
  description varchar(256),
  update_time timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (biz_tag)
);

INSERT INTO leaf_alloc(biz_tag, max_id, step, description)
VALUES ('order', 1, 1000, '订单ID');

4、初始化 Leaf Bean

@Component
public class LeafIdGenerator {

    private SegmentIDGenImpl idGen;

    @PostConstruct
    public void init() {
        idGen = new SegmentIDGenImpl();

        // 配置数据源
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/leaf");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        idGen.setDataSource(dataSource);
        idGen.init();
    }

    public long nextId(String key) {
        Result result = idGen.get(key);
        if (result.getStatus() == Status.SUCCESS) {
            return result.getId();
        }
        throw new RuntimeException("生成ID失败");
    }
}

5、使用(业务代码)

@RestController
public class OrderController {

    @Autowired
    private LeafIdGenerator idGenerator;

    @GetMapping("/id")
    public Long getId() {
        return idGenerator.nextId("order");
    }
}
Snowflake 模式

直接用算法“算出ID”,用时间戳 + 机器ID + 序列号拼成一个全局唯一ID

推荐在高并发场景下使用

缺点:
- 时钟回拨风险(需要额外处理)
- 机器ID分配复杂(分布式环境下容易冲突)

流程:

1、配置依赖,同上

2、 配置 Zookeeper

需要部署:
Apache ZooKeeper

3、 初始化代码

@Component
public class SnowflakeIdGenerator {

    private SnowflakeIDGenImpl idGen;

    @PostConstruct
    public void init() throws Exception {
        idGen = new SnowflakeIDGenImpl("127.0.0.1:2181", 8081);
        idGen.init();
    }

    public long nextId() {
        Result result = idGen.get("test");
        if (result.getStatus() == Status.SUCCESS) {
            return result.getId();
        }
        throw new RuntimeException("生成ID失败");
    }
}
对比
维度 Segment Snowflake
生成方式 数据库分配号段 算法计算
性能 高(内存操作) 极高
依赖 数据库 时间 + 机器ID
是否去中心化
稳定性 中(受时间影响)
推荐场景 主流业务 超高并发/分布式

参考

Leaf——美团点评分布式ID生成系统 - 美团技术团队

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐