From 32e00f9438ed29fc26351f65cf7d98eefd1d838e Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期五, 08 十二月 2023 14:26:21 +0800
Subject: [PATCH] 换个雪花算法
---
go.sum | 5 -
go.mod | 7 +-
pkg/snowflake/snowflake.go | 140 +++++++++++++++++++++++++++++++++++++---------
3 files changed, 115 insertions(+), 37 deletions(-)
diff --git a/go.mod b/go.mod
index fca578c..25b2113 100644
--- a/go.mod
+++ b/go.mod
@@ -9,6 +9,7 @@
basic.com/valib/bhomedbapi.git v0.0.0-20220825084023-fe74ddd6ae6e
github.com/apache/plc4x/plc4go v0.0.0-20230817065839-dd203446b558
github.com/gin-contrib/cors v1.4.0
+ github.com/gin-contrib/pprof v1.4.0
github.com/gin-gonic/gin v1.9.1
github.com/go-co-op/gocron v1.32.1
github.com/go-redis/redis/v8 v8.11.4
@@ -19,8 +20,10 @@
github.com/jinzhu/gorm v1.9.16
github.com/mitchellh/mapstructure v1.5.0
github.com/mojocn/base64Captcha v1.3.1
+ github.com/muesli/cache2go v0.0.0-20221011235721-518229cd8021
github.com/nsqio/go-nsq v1.1.0
github.com/robfig/cron/v3 v3.0.1
+ github.com/satori/go.uuid v1.2.0
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/shopspring/decimal v1.3.1
github.com/songzhibin97/gkit v1.2.10
@@ -41,7 +44,6 @@
github.com/IBM/netaddr v1.5.0 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/ajg/form v1.5.1 // indirect
- github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
@@ -50,7 +52,6 @@
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
- github.com/gin-contrib/pprof v1.4.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
@@ -84,14 +85,12 @@
github.com/mattn/go-sqlite3 v1.14.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
- github.com/muesli/cache2go v0.0.0-20221011235721-518229cd8021 // indirect
github.com/onsi/gomega v1.27.4 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/rs/zerolog v1.30.0 // indirect
- github.com/satori/go.uuid v1.2.0 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
diff --git a/go.sum b/go.sum
index c5660cd..a5b768d 100644
--- a/go.sum
+++ b/go.sum
@@ -63,9 +63,6 @@
github.com/apache/plc4x/plc4go v0.0.0-20230817065839-dd203446b558 h1:d3INvMf4ei9qlX10We5+z/+dQnmmCx0J0wflcZVihGo=
github.com/apache/plc4x/plc4go v0.0.0-20230817065839-dd203446b558/go.mod h1:KC3Kj7xv0dlGb5yT1+Mz9cI9YZj1RD19cr8TyqfnBDU=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
-github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
-github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
-github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
@@ -277,7 +274,6 @@
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -421,7 +417,6 @@
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
-go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
diff --git a/pkg/snowflake/snowflake.go b/pkg/snowflake/snowflake.go
index 049b307..f0f6442 100644
--- a/pkg/snowflake/snowflake.go
+++ b/pkg/snowflake/snowflake.go
@@ -2,26 +2,18 @@
import (
"apsClient/pkg/logx"
+ "errors"
"fmt"
- "github.com/bwmarrin/snowflake"
"hash/fnv"
"net"
+ "strconv"
+ "sync"
+ "time"
)
-var Node *snowflake.Node
+var idGenerater *IdWorker
-func Init(nodeId int64) error {
- // Create a new Node with a Node number of 0~1023
- var err error
- Node, err = snowflake.NewNode(nodeId)
- if err != nil {
- logx.Errorf("snowflake NewNode error:%v", err)
- return err
- }
- return nil
-}
-
-func InitWithIP() {
+func init() {
// 浣跨敤 LookupIP 鑾峰彇涓绘満鐨� IP 鍦板潃鍒楄〃
// 鑾峰彇鏈満鎵�鏈夌綉缁滄帴鍙�
interfaces, err := net.Interfaces()
@@ -69,20 +61,11 @@
logx.Errorf("snowflake can not generate, init error, ip to number error :%v", err)
panic(fmt.Sprintf("snowflake can not generate, init error, ip to number error :%v", err))
}
- err = Init(ipNumber)
+ idGenerater, err = NewIdWorker(ipNumber)
if err != nil {
logx.Errorf("snowflake can not generate, init error :%v", err)
panic(fmt.Sprintf("snowflake can not generate, init error :%v", err))
}
-}
-
-func StringToNumber(input string) (int64, error) {
- hash := fnv.New32a()
- _, err := hash.Write([]byte(input))
- if err != nil {
- return 0, err
- }
- return int64(hash.Sum32() % 1024), nil // 鍙栦綑鏁扮‘淇濈粨鏋滃湪 1 鍒� 1023 涔嬮棿
}
func ipToNumber(ip string) (int64, error) {
@@ -98,9 +81,110 @@
return int64(hash.Sum32() % 1024), nil // 鍙栦綑鏁扮‘淇濈粨鏋滃湪 1 鍒� 1023 涔嬮棿
}
-func GenerateID() int64 {
- if Node == nil {
- InitWithIP()
+const (
+ CEpoch = 1474802888000
+ CWorkerIdBits = 10 // Num of WorkerId Bits
+ CSenquenceBits = 12 // Num of Sequence Bits
+
+ CWorkerIdShift = 12
+ CTimeStampShift = 22
+
+ CSequenceMask = 0xfff // equal as getSequenceMask()
+ CMaxWorker = 0x3ff // equal as getMaxWorkerId()
+)
+
+type IdWorker struct {
+ workerId int64
+ lastTimeStamp int64
+ sequence int64
+ maxWorkerId int64
+ lock *sync.Mutex
+}
+
+func NewIdWorker(workerId int64) (iw *IdWorker, err error) {
+ iw = new(IdWorker)
+
+ iw.maxWorkerId = getMaxWorkerId()
+
+ if workerId > iw.maxWorkerId || workerId < 0 {
+ return nil, errors.New("worker not fit")
}
- return int64(Node.Generate())
+ iw.workerId = workerId
+ iw.lastTimeStamp = -1
+ iw.sequence = 0
+ iw.lock = new(sync.Mutex)
+ return iw, nil
+}
+
+func getMaxWorkerId() int64 {
+ return -1 ^ -1<<CWorkerIdBits
+}
+
+func getSequenceMask() int64 {
+ return -1 ^ -1<<CSenquenceBits
+}
+
+// return in ms
+func (iw *IdWorker) timeGen() int64 {
+ return time.Now().UnixNano() / 1000 / 1000
+}
+
+func (iw *IdWorker) timeReGen(last int64) int64 {
+ ts := time.Now().UnixNano() / 1000 / 1000
+ for {
+ if ts <= last {
+ ts = iw.timeGen()
+ } else {
+ break
+ }
+ }
+ return ts
+}
+
+func (iw *IdWorker) NextId() (ts int64, err error) {
+ iw.lock.Lock()
+ defer iw.lock.Unlock()
+ ts = iw.timeGen()
+ if ts == iw.lastTimeStamp {
+ iw.sequence = (iw.sequence + 1) & CSequenceMask
+ if iw.sequence == 0 {
+ ts = iw.timeReGen(ts)
+ }
+ } else {
+ iw.sequence = 0
+ }
+
+ if ts < iw.lastTimeStamp {
+ err = errors.New("Clock moved backwards, Refuse gen id")
+ return 0, err
+ }
+ iw.lastTimeStamp = ts
+ ts = (ts-CEpoch)<<CTimeStampShift | iw.workerId<<CWorkerIdShift | iw.sequence
+ return ts, nil
+}
+
+func ParseId(id int64) (t time.Time, ts int64, workerId int64, seq int64) {
+ seq = id & CSequenceMask
+ workerId = (id >> CWorkerIdShift) & CMaxWorker
+ ts = (id >> CTimeStampShift) + CEpoch
+ t = time.Unix(ts/1000, (ts%1000)*1000000)
+ return
+}
+
+func GenerateID() int64 {
+start:
+ id, err := idGenerater.NextId()
+ if err != nil {
+ goto start
+ }
+ return id
+}
+
+func GenerateIdStr() string {
+start:
+ id, err := idGenerater.NextId()
+ if err != nil {
+ goto start
+ }
+ return strconv.FormatInt(id, 10)
}
--
Gitblit v1.8.0