This commit is contained in:
李子铭 2025-03-19 14:27:49 +08:00
parent 457381a85c
commit 0edea515c8
7 changed files with 192 additions and 21 deletions

3
go.mod
View File

@ -38,6 +38,7 @@ require (
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/emirpasic/gods v1.12.0 // indirect
@ -61,7 +62,7 @@ require (
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect

4
go.sum
View File

@ -24,6 +24,8 @@ github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
@ -163,6 +165,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=

View File

@ -4,7 +4,6 @@ import "context"
// GenerateMixRepo interface
type GenerateMixRepo interface {
// GeneratorString 生成字符串
GeneratorString(ctx context.Context, workId int) (string, error)
GeneratorNumber(ctx context.Context, workId int) (uint64, error)
}

View File

@ -2,9 +2,10 @@ package mixrepoimpl
import (
"context"
"github.com/bwmarrin/snowflake"
"hash/fnv"
"math"
"strconv"
"os"
"voucher/internal/biz/mixrepos"
"voucher/internal/data"
"voucher/internal/pkg/uid"
@ -12,38 +13,64 @@ import (
type GenerateRepoImpl struct {
rdb *data.Rdb
node *snowflake.Node
}
func NewGenerateMixRepoImpl(rdb *data.Rdb) mixrepos.GenerateMixRepo {
return &GenerateRepoImpl{rdb: rdb}
func NewGenerateMixRepoImpl(rdb *data.Rdb) (mixrepos.GenerateMixRepo, error) {
g := &GenerateRepoImpl{rdb: rdb}
name, err := os.Hostname()
if err != nil {
return nil, err
}
serverId := g.hashMod(name)
node, err := snowflake.NewNode(int64(serverId))
if err != nil {
return nil, err
}
g.node = node
return g, nil
}
// GeneratorString 生成字符串
func (s *GenerateRepoImpl) GeneratorString(ctx context.Context, workId int) (string, error) {
serverIdStr := uid.GetAppId(ctx)
serverId := s.hashMod(serverIdStr)
number, err := uid.NewSignGenerator(s.rdb.Rdb).SetWorkerID(workId).SetServerID(serverId).GetNumber()
if err != nil {
return "", err
}
return strconv.FormatUint(number, 10), nil
func (s *GenerateRepoImpl) GeneratorString(_ context.Context, workId int) (string, error) {
return s.node.Generate().String(), nil
//serverIdStr := uid.GetAppId(ctx)
//serverId := s.hashMod(serverIdStr)
//
//number, err := uid.NewSignGenerator(s.rdb.Rdb).SetWorkerID(workId).SetServerID(serverId).GetNumber()
//if err != nil {
// return "", err
//}
//
//return strconv.FormatUint(number, 10), nil
}
// GeneratorNumber 生成unit64
func (s *GenerateRepoImpl) GeneratorNumber(ctx context.Context, workId int) (uint64, error) {
serverIdStr := uid.GetAppId(ctx)
serverId := s.hashMod(serverIdStr)
number, err := uid.NewSignGenerator(s.rdb.Rdb).SetWorkerID(workId).SetServerID(serverId).GetNumber()
if err != nil {
return 0, err
}
return number, nil
}
// hashMod hash mod
func (s *GenerateRepoImpl) hashMod(hashStr string) int {
hash := fnv.New32a()
hash.Write([]byte(hashStr))
_, _ = hash.Write([]byte(hashStr))
hashValue := hash.Sum32()
return int(math.Mod(float64(hashValue), 32))
}

View File

@ -4,15 +4,19 @@ import (
"context"
"fmt"
"math"
"os"
"strconv"
"sync/atomic"
"time"
"github.com/redis/go-redis/v9"
)
const (
Order = 1 // Order
OrderWechat = 2 // OrderWechat
Order = 1
)
const (
BitsFull = 64 //
BitsPre = 1 // 固定
BitsTime = 41 // 毫秒时间戳 可以最多支持69年
@ -38,6 +42,7 @@ func (sg *SignGenerator) GetNumber() (uint64, error) {
if sg.ServerID < 0 || sg.ServerID > 31 {
return 0, fmt.Errorf("serverID is lost")
}
if sg.WorkerID < 0 || sg.WorkerID > 31 {
return 0, fmt.Errorf("workerID is lost")
}
@ -131,3 +136,27 @@ func (sg *SignGenerator) ReverseNumber(number uint64) map[string]interface{} {
return uuidItem
}
var num int64
func GenerateNo() string {
t := time.Now()
s := t.Format("20060102150405")
m := t.UnixNano()/1e6 - t.UnixNano()/1e9*1e3
ms := sup(m, 3)
p := os.Getpid() % 1000
ps := sup(int64(p), 3)
i := atomic.AddInt64(&num, 1)
r := i % 10000
rs := sup(r, 4)
n := fmt.Sprintf("%s%s%s%s", s, ms, ps, rs)
return n
}
func sup(i int64, n int) string {
m := fmt.Sprintf("%d", i)
for len(m) < n {
m = fmt.Sprintf("0%s", m)
}
return m
}

View File

@ -1,6 +1,13 @@
package uid
import (
"context"
"fmt"
"github.com/bwmarrin/snowflake"
"hash/fnv"
"math"
"os"
"sync"
"testing"
"github.com/redis/go-redis/v9"
@ -8,15 +15,119 @@ import (
func TestSignGenerator_GetNumber(t *testing.T) {
rdb := redis.NewClient(&redis.Options{
Addr: "",
Password: "",
DB: 0,
Addr: "47.97.27.195:6379",
Password: "lansexiongdi@666",
DB: 15,
})
number, err := NewSignGenerator(rdb).SetWorkerID(1).SetServerID(2).GetNumber()
t.Log(number, err)
if err != nil {
t.Error(err)
return
}
t.Log(number)
}
func TestSignGenerator_Num(t *testing.T) {
rdb := redis.NewClient(&redis.Options{
Addr: "47.97.27.195:6379",
Password: "lansexiongdi@666",
DB: 15,
})
var ids sync.Map
var wg sync.WaitGroup
const concurrency = 2000
wg.Add(concurrency)
for i := 0; i < concurrency; i++ {
go func() {
defer wg.Done()
id, err := NewSignGenerator(rdb).SetWorkerID(1).SetServerID(2).GetNumber()
if err != nil {
t.Error(err)
return
}
if _, exists := ids.LoadOrStore(id, true); exists {
t.Errorf("duplicate ID generated")
}
}()
}
wg.Wait()
}
func TestSignGenerator_ReverseNumber(t *testing.T) {
reverseNumber := NewSignGenerator(nil).ReverseNumber(556081583078248449)
t.Log(reverseNumber)
}
func Test_GenerateNo(t *testing.T) {
//no := GenerateNo()
//
//t.Log(len(no))
//t.Log(no)
p := os.Getpid()
t.Log(p)
t.Log(p % 1000)
//uid := uuid.New().String()
//t.Log(len(uid))
//t.Log(uid)
ctx := context.Background()
serverIdStr := GetAppId(ctx)
t.Log(serverIdStr)
t.Log(hashMod(serverIdStr))
node, err := snowflake.NewNode(1023)
if err != nil {
t.Error(err)
return
}
nid := node.Generate().String()
t.Log(len(nid))
t.Log(nid)
}
func hashMod(hashStr string) int {
hash := fnv.New32a()
_, _ = hash.Write([]byte(hashStr))
hashValue := hash.Sum32()
return int(math.Mod(float64(hashValue), 32))
}
func GenerateSnowflakeID(nodeID int64) (string, error) {
if nodeID < 0 || nodeID > 1023 {
return "", fmt.Errorf("invalid node ID: %d", nodeID)
}
node, err := snowflake.NewNode(nodeID)
if err != nil {
return "", err
}
return node.Generate().String(), nil
}
func TestGenerateID(t *testing.T) {
nodeID := int64(1) // 确保唯一
node, _ := snowflake.NewNode(nodeID)
var ids sync.Map
var wg sync.WaitGroup
const concurrency = 2000
wg.Add(concurrency)
for i := 0; i < concurrency; i++ {
go func() {
defer wg.Done()
id := node.Generate().String()
if _, exists := ids.LoadOrStore(id, true); exists {
t.Errorf("duplicate ID generated")
}
}()
}
wg.Wait()
}

View File

@ -67,7 +67,7 @@ func (w *WechatNotifyConsumer) Start(ctx context.Context) error {
}
// consumeMessages 消费消息的具体逻辑
func (w *WechatNotifyConsumer) consumeMessages(ctx context.Context, mqConsumer mqhttpsdk.MQConsumer, tag string) {
func (w *WechatNotifyConsumer) consumeMessages2(ctx context.Context, mqConsumer mqhttpsdk.MQConsumer, tag string) {
for {
endChan := make(chan int)
respChan := make(chan mqhttpsdk.ConsumeMessageResponse)