|
|
@@ -1,230 +0,0 @@
|
|
|
-package order
|
|
|
-
|
|
|
-import (
|
|
|
- "fmt"
|
|
|
- "sync"
|
|
|
- "sync/atomic"
|
|
|
- "time"
|
|
|
-)
|
|
|
-
|
|
|
-// 更安全的版本:带毫秒时间戳
|
|
|
-type Generator struct {
|
|
|
- machineID int
|
|
|
- lastTime int64 // 上次时间(毫秒)
|
|
|
- sequence int64
|
|
|
- mu sync.Mutex
|
|
|
-}
|
|
|
-
|
|
|
-func NewOrderNoGenerator(machineID int) *Generator {
|
|
|
- return &Generator{
|
|
|
- machineID: machineID,
|
|
|
- lastTime: time.Now().UnixMilli(),
|
|
|
- sequence: 0,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (g *Generator) Generate() string {
|
|
|
- g.mu.Lock()
|
|
|
- defer g.mu.Unlock()
|
|
|
-
|
|
|
- currentTime := time.Now().UnixMilli()
|
|
|
-
|
|
|
- if currentTime == g.lastTime {
|
|
|
- g.sequence++
|
|
|
- } else {
|
|
|
- g.sequence = 1
|
|
|
- g.lastTime = currentTime
|
|
|
- }
|
|
|
-
|
|
|
- // 格式化时间,包含毫秒
|
|
|
- t := time.UnixMilli(currentTime)
|
|
|
- // 格式:年月日时分秒 + 毫秒(3位) + 机器ID + 序列号
|
|
|
- return fmt.Sprintf("%s%03d%02d%04d",
|
|
|
- t.Format("20060102150405"), // 14位
|
|
|
- t.Nanosecond()/1e6, // 3位毫秒
|
|
|
- g.machineID, // 2位
|
|
|
- g.sequence, // 4位
|
|
|
- )
|
|
|
-}
|
|
|
-
|
|
|
-// GenerateString 生成字符串格式订单号
|
|
|
-func (g *Generator) GenerateString(prefix string) string {
|
|
|
- // 调用无锁Generate获取ID
|
|
|
- id := g.Generate()
|
|
|
-
|
|
|
- // 格式化为字符串
|
|
|
- return fmt.Sprintf("%s%s", prefix, id)
|
|
|
-}
|
|
|
-
|
|
|
-type GeneratorV3 struct {
|
|
|
- machineID int
|
|
|
- // 使用一个64位整数存储时间戳(42位)和序列号(22位)
|
|
|
- // 这样可以原子操作,不需要锁
|
|
|
- counter uint64
|
|
|
-}
|
|
|
-
|
|
|
-func NewOrderNoGeneratorV3(machineID int) *GeneratorV3 {
|
|
|
- return &GeneratorV3{
|
|
|
- machineID: machineID,
|
|
|
- counter: 0,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (g *GeneratorV3) Generate() string {
|
|
|
- // 获取当前毫秒时间戳
|
|
|
- now := uint64(time.Now().UnixMilli())
|
|
|
-
|
|
|
- // 原子操作获取下一个ID
|
|
|
- var lastTime, seq uint64
|
|
|
- for {
|
|
|
- old := atomic.LoadUint64(&g.counter)
|
|
|
- lastTime = old >> 22 // 高42位是时间戳
|
|
|
- seq = old & 0x3FFFFF // 低22位是序列号
|
|
|
-
|
|
|
- if now > lastTime {
|
|
|
- // 时间戳变化,重置序列号
|
|
|
- seq = 0
|
|
|
- lastTime = now
|
|
|
- } else if seq >= 0x3FFFFF { // 序列号达到最大值
|
|
|
- // 等待下一毫秒
|
|
|
- for now <= lastTime {
|
|
|
- time.Sleep(100 * time.Microsecond)
|
|
|
- now = uint64(time.Now().UnixMilli())
|
|
|
- }
|
|
|
- seq = 0
|
|
|
- lastTime = now
|
|
|
- } else {
|
|
|
- seq++
|
|
|
- }
|
|
|
-
|
|
|
- newVal := (lastTime << 22) | (seq & 0x3FFFFF)
|
|
|
- if atomic.CompareAndSwapUint64(&g.counter, old, newVal) {
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 格式化输出
|
|
|
- t := time.UnixMilli(int64(lastTime))
|
|
|
- return fmt.Sprintf("%s%03d%02d%06d",
|
|
|
- t.Format("20060102150405"),
|
|
|
- t.Nanosecond()/1e6,
|
|
|
- g.machineID,
|
|
|
- seq,
|
|
|
- )
|
|
|
-}
|
|
|
-
|
|
|
-// 并发测试函数
|
|
|
-func TestConcurrentGeneration() {
|
|
|
- fmt.Println("=== 并发测试 ===")
|
|
|
- generator := NewOrderNoGenerator(1)
|
|
|
-
|
|
|
- // 使用map检查重复
|
|
|
- results := sync.Map{}
|
|
|
- var wg sync.WaitGroup
|
|
|
- start := time.Now()
|
|
|
-
|
|
|
- // 启动1000个协程同时生成订单号
|
|
|
- for i := 0; i < 1000; i++ {
|
|
|
- wg.Add(1)
|
|
|
- go func(id int) {
|
|
|
- defer wg.Done()
|
|
|
- orderNo := generator.Generate()
|
|
|
-
|
|
|
- // 检查是否重复
|
|
|
- if _, loaded := results.LoadOrStore(orderNo, true); loaded {
|
|
|
- fmt.Printf("⚠️ 发现重复订单号: %s\n", orderNo)
|
|
|
- }
|
|
|
- }(i)
|
|
|
- }
|
|
|
-
|
|
|
- wg.Wait()
|
|
|
- elapsed := time.Since(start)
|
|
|
-
|
|
|
- // 统计结果
|
|
|
- count := 0
|
|
|
- results.Range(func(key, value interface{}) bool {
|
|
|
- count++
|
|
|
- return true
|
|
|
- })
|
|
|
-
|
|
|
- fmt.Printf("生成 %d 个订单号,耗时 %v\n", count, elapsed)
|
|
|
- fmt.Printf("平均每秒生成: %.0f 个\n", float64(count)/elapsed.Seconds())
|
|
|
-}
|
|
|
-
|
|
|
-// 测试V3版本的并发
|
|
|
-func TestConcurrentGenerationV3() {
|
|
|
- fmt.Println("\n=== 测试V3版本并发 ===")
|
|
|
- generator := NewOrderNoGeneratorV3(1)
|
|
|
-
|
|
|
- results := sync.Map{}
|
|
|
- var wg sync.WaitGroup
|
|
|
- start := time.Now()
|
|
|
-
|
|
|
- // 启动10000个协程同时生成订单号
|
|
|
- for i := 0; i < 10000; i++ {
|
|
|
- wg.Add(1)
|
|
|
- go func(id int) {
|
|
|
- defer wg.Done()
|
|
|
- orderNo := generator.Generate()
|
|
|
-
|
|
|
- // 检查是否重复
|
|
|
- if _, loaded := results.LoadOrStore(orderNo, true); loaded {
|
|
|
- fmt.Printf("⚠️ V3 - 发现重复订单号: %s\n", orderNo)
|
|
|
- }
|
|
|
- }(i)
|
|
|
- }
|
|
|
-
|
|
|
- wg.Wait()
|
|
|
- elapsed := time.Since(start)
|
|
|
-
|
|
|
- // 统计结果
|
|
|
- count := 0
|
|
|
- results.Range(func(key, value interface{}) bool {
|
|
|
- count++
|
|
|
- return true
|
|
|
- })
|
|
|
-
|
|
|
- fmt.Printf("V3 - 生成 %d 个订单号,耗时 %v\n", count, elapsed)
|
|
|
- fmt.Printf("V3 - 平均每秒生成: %.0f 个\n", float64(count)/elapsed.Seconds())
|
|
|
-}
|
|
|
-
|
|
|
-// 压力测试:持续生成订单号
|
|
|
-func StressTest() {
|
|
|
- fmt.Println("\n=== 压力测试 ===")
|
|
|
- generator := NewOrderNoGeneratorV3(1)
|
|
|
-
|
|
|
- results := sync.Map{}
|
|
|
- duplicateCount := 0
|
|
|
- var duplicateMutex sync.Mutex
|
|
|
-
|
|
|
- // 持续生成5秒
|
|
|
- stop := time.After(5 * time.Second)
|
|
|
- start := time.Now()
|
|
|
-
|
|
|
- for i := 0; ; i++ {
|
|
|
- select {
|
|
|
- case <-stop:
|
|
|
- elapsed := time.Since(start)
|
|
|
- totalCount := 0
|
|
|
- results.Range(func(key, value interface{}) bool {
|
|
|
- totalCount++
|
|
|
- return true
|
|
|
- })
|
|
|
-
|
|
|
- fmt.Printf("压力测试 - 总生成: %d 个订单号\n", i)
|
|
|
- fmt.Printf("压力测试 - 唯一订单号: %d 个\n", totalCount)
|
|
|
- fmt.Printf("压力测试 - 重复数: %d 个\n", duplicateCount)
|
|
|
- fmt.Printf("压力测试 - 耗时: %v\n", elapsed)
|
|
|
- fmt.Printf("压力测试 - QPS: %.0f\n", float64(i)/elapsed.Seconds())
|
|
|
- return
|
|
|
-
|
|
|
- default:
|
|
|
- orderNo := generator.Generate()
|
|
|
- if _, loaded := results.LoadOrStore(orderNo, true); loaded {
|
|
|
- duplicateMutex.Lock()
|
|
|
- duplicateCount++
|
|
|
- duplicateMutex.Unlock()
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|