问题:Golang 使用UnixNano()作为唯一键id,在高并发环境下出现重复,
package main
import (
"fmt"
"github.com/fwhezfwhez/go-queue"
"runtime"
"strconv"
"sync"
"time"
)
var mutex sync.Mutex
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
wg := sync.WaitGroup{}
var loopCount int = 5000
var queue = Queue.NewEmpty()
for i := 0; i < loopCount; i++ {
wg.Add(1)
go func(in int, q *Queue.Queue) {
tmp := getNum()
q.SafePush(tmp)
fmt.Println("finish " + strconv.Itoa(in) + ",produce:" + strconv.FormatInt(tmp, 10))
wg.Done()
}(i, queue)
}
wg.Wait()
//queue.Print() // 输入所有UUID
if (queue.ValidLength() == loopCount) {
fmt.Println("生成", loopCount, "个UUID数量,没发现重复,继续测试。")
fmt.Println("备注:若运行没有输出,证明是有重复,程序结束。")
}
}
func getNum() int64 {
mutex.Lock()
defer mutex.Unlock()
return time.Now().UnixNano()
}
运行结果,发现重复:
改进版本-1:数字UUID改进版 (unixNano + hashCode(uuid))
package main
import (
"fmt"
"github.com/fwhezfwhez/go-queue"
uuid "github.com/satori/go.uuid"
"hash/crc32"
"runtime"
"strconv"
"sync"
"time"
)
var mutex sync.Mutex
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
wg := sync.WaitGroup{}
var loopCount int = 5000
var queue = Queue.NewEmpty()
for i := 0; i < loopCount; i++ {
wg.Add(1)
go func(in int, q *Queue.Queue) {
tmp := getNum()
q.SafePush(tmp)
fmt.Println("finish " + strconv.Itoa(in) + ",produce:" + tmp)
wg.Done()
}(i, queue)
}
wg.Wait()
//queue.Print() // 输入所有UUID
if (queue.ValidLength() == loopCount) {
fmt.Println("生成", loopCount, "个UUID数量,没发现重复,继续测试。")
fmt.Println("备注:若运行没有输出,证明是有重复,程序结束。")
}
}
//改进方法
func getNum() string {
mutex.Lock()
defer mutex.Unlock()
currentTime := time.Now()
timestamp := currentTime.UnixNano()
uuid,_ := uuid.NewV4()
uuidHash := int(crc32.ChecksumIEEE([]byte(uuid.String())))
if -uuidHash >= 0 {
uuidHash = -uuidHash
}
uuidStr := strconv.FormatInt(timestamp,10)+strconv.Itoa(uuidHash)
return uuidStr
}