客户端代码:
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
}
     1 
                    
                    lqs      2020-02-15 20:38:06 +08:00 
                    
                    每次都 Init 当然会一样了 
                 | 
            
     2 
                    
                    OllyDebug      2020-02-15 22:20:18 +08:00 via iPhone 
                    
                    代码的锅 
                 | 
            
     3 
                    
                    jingege      2020-02-15 22:36:15 +08:00 via Android 
                    
                    我知道有个 nug,但是其实很容易发现,我决定先不告诉你 
                 | 
            
     4 
                    
                    stevenhawking      2020-02-15 23:05:03 +08:00 
                    
                    @jingege 我知道你这句话有个 nug,但是其实很容易发现,我决定先不告诉你 
                 | 
            
     5 
                    
                    swulling      2020-02-16 01:40:01 +08:00 via iPhone 
                    
                    用法有问题,时间 workerID 序列号都相同 
                 | 
            
     6 
                    
                    sunmoon1983   OP  | 
            
     7 
                    
                    sunmoon1983   OP @swulling 大老,指点一下?循环里面要怎么用? 
                 | 
            
     8 
                    
                    sunmoon1983   OP 感谢大家, 
                @lqs 谢谢,我把 INIT 拿出来就可以了  | 
            
     9 
                    
                    beiping96      2020-02-17 13:19:02 +08:00 
                    
                    另外还有一个点,如果生成 snowflake ID 的节点 在小于几 ms 内完成重启的话,也是会发生重复的 
                 | 
            
     10 
                    
                    zunceng      2020-02-26 13:23:45 +08:00 
                    
                    
                 | 
            
     11 
                    
                    yuechen323      2020-04-23 10:49:53 +08:00 
                    
                    基于 SnowFlake 简单是简单, 但是需要二次开发 
                在每个应用内, 多线程情况下, 且高并发是一定会出现重复的, 因此生成 id 的服务一定要做成独立的服务 且生成 id 的进程一定是单线程, 可以用池化技术进行预分配 id 来优化速度 如果 id 服务要做成集群, 那么 dataCenterId 一定设置成不一样的, 这就变成了有状态服务 有状态服务如何优化呢? 可以在启动 id 服务的时候, 从 redis 啊, zookeeper 里面原子的获取自增 id 来实现 这样就可以无脑的部署多个点了 Peace~  |