什么是雪花算法
雪花算法
- 一、背景
- 分库分表
- **性能瓶颈和单点故障**
- **UUID**
- 二、设计思路
- 三、ID 的结构(64 位 long 型)
- 四、优缺点
- 五、应用场景
一、背景
在互联网早期,系统都是 单机 + 单库,用数据库的 自增主键 就能满足唯一 ID 的需求
但后来进入 分布式系统 时代,问题就出现了:
- 多个数据库分库分表时,自增主键可能冲突
- 跨数据中心时,统一发号中心容易成为 性能瓶颈和单点故障
- UUID 虽然唯一,但 太长(128 位)、无序,在数据库索引中性能很差
于是 Twitter 提出了 Snowflake(雪花算法),作为一种 分布式 ID 生成方案(可以在自己机器本地生成唯一 ID )
下面对出现的问题解释一下
分库分表
为什么分库分表:
系统小的时候,数据库里的几万、几十万数据,放在一个表里没问题
但是随着业务增长,数据可能来到上亿行,而一个表中的存储空间、并发能力 又是有限的,那再仅仅用一张表存储数据肯定是不可行的,就像你开学搬行李的时候,一趟搬不上楼怎么办,要么找人帮你搬,要么分几趟搬,数据也是一样的,既然存不下,那就分开存
举个例子来加深对分库分表的理解
想象一个 超市仓库:
- 一开始商品少,用一个大仓库存放就行(单库单表)
- 货物越来越多,仓库爆满,就建多个仓库(分库)
- 每个仓库里,货架也太满了,就把货物拆到多个货架上(分表)
这样每个仓库、每个货架的压力都减小了
性能瓶颈和单点故障
性能瓶颈 ,很好理解,就是性能出现问题,比较某游戏服务器爆了,学校选课平台因为访问的人太多进不去
单点故障,整个分布式系统被 一个点 卡死,系统的可用性大幅降低
比如
村里只有一个井,一旦这口井干了,全村人都打不上水了
UUID
UUID(Universally Unique Identifier,全局唯一标识符)是一个 128 位的字符串
比如:
550e8400-e29b-41d4-a716-446655440000
它的好处就是 只要生成算法没问题,几乎不会重复 → 保证唯一性
伴随优点而来的是缺点,它主要有两个缺点
太长:
UUID 是 128 位,通常用 36 个字符的字符串 来存储(带 4 个 -),这导致它占用的空间很大,而且 每条记录的索引变大,数据库的 B+ 树索引页能放的数据更少了,也会导致磁盘 I/O 和搜索效率变差
无序
数据库里,主键索引(B+ 树)默认是有序存储的:
- 如果主键是自增 ID,数据会 顺序插入,索引树只会往右边加,很高效
- 如果主键是 UUID,这些字符串是随机分布的,插入时要到处找地方塞
比如
假设 B+ 树索引像一本电话簿:
- 自增 ID:新号码总是递增,就像在最后一页不断加数据 → 很快
- UUID:新号码是随机的 → 有可能插到前面、中间,导致频繁的 页分裂、索引重排,性能很差
二、设计思路
雪花算法的核心思想就是 让每台机器在本地就能独立生成唯一 ID,不依赖数据库或中心服务
要保证:
- 唯一性:不同机器不会生成相同 ID
- 高性能:生成 ID 不需要网络通信,直接在内存里算
- 趋势有序:ID 大体上随着时间递增,利于数据库索引
三、ID 的结构(64 位 long 型)
经典的 Twitter 版雪花 ID 结构如下:
**0 | 41位时间戳 | 10位机器ID | 12位序列号**
解释:
- 1 位符号位
永远是 0(保证正数) - 41 位时间戳
记录毫秒时间,可以用 69 年
确保 ID 大体上随时间递增 - 10 位机器 ID
用来区分不同机器(最多 1024 台)
- 可以拆成 5 位数据中心 ID + 5 位机器 ID
- 12 位序列号
每台机器在同一毫秒内,最多生成 4096(2^12) 个 不重复ID
如果超出,就等待下一毫秒
所以一个雪花 ID 本质上就是 时间戳 + 机器编号 + 序列号 的拼接结果
四、优缺点
优点
- 高性能:本地生成,不依赖数据库或中心节点
- 全局唯一:时间戳 + 机器 ID + 序列号,避免冲突
- 趋势有序:按时间大体递增,利于数据库写入性能
- 分布式可扩展:支持上千台机器同时生成
缺点
- 依赖机器时间:如果系统时钟回拨,可能生成重复 ID
- 时间戳有限:41 位只能用约 69 年
- 不严格递增:同一毫秒多机器生成的 ID,可能数值顺序打乱
五、应用场景
雪花算法特别适合 分布式高并发系统:
- 订单号:电商系统(双十一秒杀,分布式生成订单 ID)
- 用户 ID / 评论 ID:社交网络里,每秒数万请求要唯一 ID
- 日志系统 / 消息系统:Kafka 消息 ID,分布式日志流水号
- 数据库主键:替代自增主键,避免分库分表冲突