Golang Go语言中 snowflake 算法生成的 id 也能重复?
Golang Go语言中 snowflake 算法生成的 id 也能重复?
客户端代码:
func GenerateID() (string, error) {
c := connect.Instance() //连接 grpc
cc, cancel := c.ServerClient()
defer cancel()
//生成 id
r, err := cc.GenerateSnowflakeID(c.Ctx, &serv.GenerateSnowflakeRequest{WorkID:"1"})
if err != nil {
return "", err
}
return r.GetMessage(), err
}
func main() {
data := ""
for i:=0;i<=100;i++{
id, err := GenerateID()
str := gconv.String(id)
fmt.Println("ID(运行到第"+gconv.String(i+1)+"条):"+str+",长度:"+gconv.String(len(str)))
if strings.Contains(data,","+str+","){
fmt.Println("ID 重复(运行到第"+gconv.String(i+1)+"条):"+str)
break
}else{
if err != nil{
fmt.Println(err.Error())
}
data = data+","+str+","
}
}
}
生成结果
sunmoondeMacBook-Pro:client_test sunmoon$ go run main.go
ID(运行到第 1 条):1581769199913537536,长度:19
ID(运行到第 2 条):1581769199913537536,长度:19
ID 重复(运行到第 2 条):1581769199913537536
服务端代码
// GenerateSnowflakeID 生成 ID
func (s *Server) GenerateSnowflakeID(ctx context.Context, in *serv.GenerateSnowflakeRequest) (re *serv.GenerateReply, err error) {
gen, err := snowflake.New().SetWorkerID(gconv.Int64(in.GetWorkID())).Init()
if err != nil {
glog.Line(true).Println(err.Error())
return
}
id, err := gen.Generate()
if err != nil {
glog.Line(true).Println(err.Error())
return
}
//id := s.GetWuid()
re = &serv.GenerateReply{Message: gconv.String(id)}
return
}
更多关于Golang Go语言中 snowflake 算法生成的 id 也能重复?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
每次都 Init 当然会一样了
更多关于Golang Go语言中 snowflake 算法生成的 id 也能重复?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
代码的锅
我知道有个 nug,但是其实很容易发现,我决定先不告诉你
我知道你这句话有个 nug,但是其实很容易发现,我决定先不告诉你
用法有问题,时间 workerID 序列号都相同
init 里面有判断,如果已经初始化了
if sfg.isHaveInit {
return sfg, nil
}
大老,指点一下?循环里面要怎么用?
感谢大家,
谢谢,我把 INIT 拿出来就可以了
另外还有一个点,如果生成 snowflake ID 的节点 在小于几 ms 内完成重启的话,也是会发生重复的
基于 SnowFlake 简单是简单, 但是需要二次开发
在每个应用内, 多线程情况下, 且高并发是一定会出现重复的, 因此生成 id 的服务一定要做成独立的服务
且生成 id 的进程一定是单线程, 可以用池化技术进行预分配 id 来优化速度
如果 id 服务要做成集群, 那么 dataCenterId 一定设置成不一样的, 这就变成了有状态服务
有状态服务如何优化呢?
可以在启动 id 服务的时候, 从 redis 啊, zookeeper 里面原子的获取自增 id 来实现
这样就可以无脑的部署多个点了
Peace~
在Go语言中,使用Snowflake算法生成的ID在理论上应该是全局唯一的,但在某些特定情况下确实存在重复的可能性。这主要源于以下几个方面:
-
时间回拨:如果系统时间突然回退(如NTP服务异常调整时间),可能导致生成的ID小于之前已生成的ID,进而在后续生成过程中产生重复。为避免此问题,通常需要实现时间回拨的检测和处理机制。
-
机器ID冲突:Snowflake算法中的机器ID用于区分不同的节点。如果不同节点被错误地配置为相同的机器ID,则这些节点生成的ID可能会冲突。因此,确保每个节点的机器ID唯一至关重要。
-
序列号溢出:尽管Snowflake算法设计的序列号部分在大多数情况下足以保证唯一性,但在极端高并发场景下,如果单毫秒内生成的ID数量超过序列号位数能表示的最大值,也可能导致重复。这通常要求系统具备足够的负载能力和优化策略。
-
实现错误:如果Snowflake算法的实现存在bug或配置不当,也可能导致ID重复。因此,使用成熟、经过验证的库是减少此类风险的关键。
总之,虽然Snowflake算法在正常情况下能有效生成全局唯一ID,但在特定条件下仍可能出现重复。通过合理设计系统架构、选择可靠的库以及实施必要的安全措施,可以最大程度地降低这种风险。