雪花算法简述及实现(hutool、美团leaf)
学习整理,如有错误,欢迎指正
雪花算法
概述:
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 |
| 是否去中心化 | 否 | 是 |
| 稳定性 | 高 | 中(受时间影响) |
| 推荐场景 | 主流业务 | 超高并发/分布式 |
参考
更多推荐




所有评论(0)