写商城的时候想用雪花算法生成订单号与用户号等信息
原来生成的订单号大概16-19位左右,有点太长,一秒几百万个ID对于普通的小商城网站也用不上这么长的
就简单的改了一下,改成一秒钟生成订单号256-512条左右就好了,节点ID也不需要255个以内,只需要一个节点ID就好了
优化完后的代码如下
package main
import (
"fmt"
"sync"
"time"
)
func main() {
id:=GetSnowflakeId1()
fmt.Println(id)
}
func GetSnowflakeId1() (id int64) {
worker:= NewWorker1()
return worker.GetId()
}
// 定义一个woker工作节点所需要的基本参数
type Worker1 struct {
mu sync.Mutex // 添加互斥锁 确保并发安全
timestamp int64 // 记录时间戳
number int64 // 当前毫秒已经生成的id序列号(从0开始累加) 1毫秒内最多生成4096个ID
}
// 实例化一个工作节点
func NewWorker1() (*Worker1) {
return &Worker1{timestamp: 0,number:0,}
}
func (w *Worker1) GetId() int64 {
epoch := int64(1613811738) // 设置为去年今天的时间戳...因为位数变了后,几百年都用不完,,实际可以设置上线日期的
idlength := uint(9)
w.mu.Lock()
defer w.mu.Unlock()
now := time.Now().Unix() // 时间戳由原来的毫秒变成了现在的秒
if w.timestamp == now {
w.number++
if w.number > (-1 ^ (-1 << idlength)) { //此处为最大节点ID,大概是2^9-1 511条,
for now <= w.timestamp {
now = time.Now().Unix()
}
}
} else{
w.number = 0
w.timestamp = now // 将机器上一次生成ID的时间更新为当前时间
}
ID := int64((now-epoch)<<idlength | (int64(1) << 1) | (w.number))
return ID
}
生成后的id 8006872578 大概十位,把减去的时间戳设置为零后ID值为 834278525954 十二位数
大概就是生成的id,最大十三四位吧...也不会碰到大数转化失精问题,参考:js golang gin雪花算法生成的id返回json化精度丢失问题的解决方案-power by goblog (iq2.cn)
当然大家也可以根据自己的实际情况做一些优化,epoch设置为上线时间戳好一些
这个是以秒为单位的获取id的,如果要改成毫秒的话自己再去改吧.一般情况下,idlength最大10,一秒钟1024个ID生成基本满足日常需求了,或者改成一毫秒2个或者4个ID生成也能满足