分布式ID的特点
- 全局唯⼀性:不能出现有重复的ID标识,这是基本要求。
- 递增性:确保⽣成ID对于⽤户或业务是递增的。
- ⾼可⽤性:确保任何时候都能⽣成正确的ID。
- ⾼性能性:在⾼并发的环境下依然表现良好。
不仅仅是⽤于⽤户
ID
,实际互联⽹中有很多场景需要能够⽣成类似
MySQL
⾃增
ID
这样不断增⼤,同时⼜ 不会重复的id
。以⽀持业务中的⾼并发场景。
⽐较典型的场景有:电商促销时短时间内会有⼤量的订单涌⼊到系统,⽐如每秒
10w+
;明星出轨时微 博短时间内会产⽣⼤量的相关微博转发和评论消息。在这些业务场景下将数据插⼊数据库之前,我们需 要给这些订单和消息先分配⼀个唯⼀ID
,然后再保存到数据库中。对这个
id
的要求是希望其中能带有⼀ 些时间信息,这样即使我们后端的系统对消息进⾏了分库分表,也能够以时间顺序对这些消息进⾏排序。
snowflake算法介绍
雪花算法,它是
Twitter
开源的由
64
位整数组成分布式
ID
,性能较⾼,并且在单机上递增。
1.
第⼀位
占⽤
1bit
,其值始终是
0
,没有实际作⽤。
2.
时间戳
占⽤
41bit
,单位为毫秒,总共可以容纳约
69
年的时间。当然,我们的时间毫秒计数不会真的从1970
年开始记,那样我们的系统跑到
2039/9/7 23:47:35
就不能⽤了,所以这⾥的时间戳只是相对于某个时间的增量,⽐如我们的系统上线是2020-07-01
,那么我们完全可以把这
timestamp
当作是 从 2020-07-01 00:00:00.000
的偏移量。
3.
⼯作机器
id
占⽤
10bit
,其中⾼位
5bit
是数据中⼼
ID
,低位
5bit
是⼯作节点
ID
,最多可以容纳
1024
个节点。
4.
序列号
占⽤
12bit
,⽤来记录同毫秒内产⽣的不同
id
。每个节点每毫秒
0
开始不断累加,最多可以累加 到4095
,同⼀毫秒⼀共可以产⽣
4096
个
ID
。
SnowFlake
算法在同⼀毫秒内最多可以⽣成多少个全局唯⼀
ID
呢?
同⼀毫秒的
ID
数量
= 1024 X 4096 = 419430
snowflake的Go实现
github.com/bwmarrin/snowflake
是⼀个相当轻量化的
snowflake
的
Go
实现。
package snowflake
import (
sf "github.com/bwmarrin/snowflake"
"time"
)
var node *sf.Node
func Init(startTime string, machineID int64) (err error) {
var st time.Time
// 把时间字符串转换为Time,时区是UTC时区。
st, err = time.Parse("2006-01-02", startTime)
if err != nil {
return
}
// 设置起始时间
sf.Epoch = st.UnixNano() / 1000000
node, err = sf.NewNode(machineID)
return
}
func GenID() int64 {
return node.Generate().Int64()
}