github.com/hdt3213/godis@v1.2.9/lib/idgenerator/snowflake.go (about) 1 package idgenerator 2 3 import ( 4 "hash/fnv" 5 "log" 6 "sync" 7 "time" 8 ) 9 10 const ( 11 // epoch0 is set to the twitter snowflake epoch of Nov 04 2010 01:42:54 UTC in milliseconds 12 // You may customize this to set a different epoch for your application. 13 epoch0 int64 = 1288834974657 14 maxSequence int64 = -1 ^ (-1 << uint64(nodeLeft)) 15 timeLeft uint8 = 22 16 nodeLeft uint8 = 10 17 nodeMask int64 = -1 ^ (-1 << uint64(timeLeft-nodeLeft)) 18 ) 19 20 // IDGenerator generates unique uint64 ID using snowflake algorithm 21 type IDGenerator struct { 22 mu *sync.Mutex 23 lastStamp int64 24 nodeID int64 25 sequence int64 26 epoch time.Time 27 } 28 29 // MakeGenerator creates a new IDGenerator 30 func MakeGenerator(node string) *IDGenerator { 31 fnv64 := fnv.New64() 32 _, _ = fnv64.Write([]byte(node)) 33 nodeID := int64(fnv64.Sum64()) & nodeMask 34 35 var curTime = time.Now() 36 epoch := curTime.Add(time.Unix(epoch0/1000, (epoch0%1000)*1000000).Sub(curTime)) 37 38 return &IDGenerator{ 39 mu: &sync.Mutex{}, 40 lastStamp: -1, 41 nodeID: nodeID, 42 sequence: 1, 43 epoch: epoch, 44 } 45 } 46 47 // NextID returns next unique ID 48 func (w *IDGenerator) NextID() int64 { 49 w.mu.Lock() 50 defer w.mu.Unlock() 51 52 timestamp := time.Since(w.epoch).Nanoseconds() / 1000000 53 if timestamp < w.lastStamp { 54 log.Fatal("can not generate id") 55 } 56 if w.lastStamp == timestamp { 57 w.sequence = (w.sequence + 1) & maxSequence 58 if w.sequence == 0 { 59 for timestamp <= w.lastStamp { 60 timestamp = time.Since(w.epoch).Nanoseconds() / 1000000 61 } 62 } 63 } else { 64 w.sequence = 0 65 } 66 w.lastStamp = timestamp 67 id := (timestamp << timeLeft) | (w.nodeID << nodeLeft) | w.sequence 68 //fmt.Printf("%d %d %d\n", timestamp, w.sequence, id) 69 return id 70 }