add: anowflake email kafka, refa: redis connectg
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
epoch = int64(1609459200000)
|
||||
datacenterIdBits = uint(5)
|
||||
workerIdBits = uint(5)
|
||||
sequenceBits = uint(12)
|
||||
|
||||
maxDatacenterId = -1 ^ (-1 << datacenterIdBits)
|
||||
maxWorkerId = -1 ^ (-1 << workerIdBits)
|
||||
maxSequence = -1 ^ (-1 << sequenceBits)
|
||||
|
||||
workerIdShift = sequenceBits
|
||||
datacenterIdShift = sequenceBits + workerIdBits
|
||||
timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits
|
||||
)
|
||||
|
||||
type Snowflake struct {
|
||||
mu sync.Mutex
|
||||
timestamp int64
|
||||
datacenterId int64
|
||||
workerId int64
|
||||
sequence int64
|
||||
}
|
||||
|
||||
func NewSnowflake(datacenterId, workerId int64) (*Snowflake, error) {
|
||||
if datacenterId < 0 || datacenterId > maxDatacenterId {
|
||||
return nil, errors.New("datacenter id must be between 0 and 31")
|
||||
}
|
||||
if workerId < 0 || workerId > maxWorkerId {
|
||||
return nil, errors.New("worker id must be between 0 and 31")
|
||||
}
|
||||
|
||||
return &Snowflake{
|
||||
timestamp: 0,
|
||||
datacenterId: datacenterId,
|
||||
workerId: workerId,
|
||||
sequence: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Snowflake) NextID() (int64, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
if now < s.timestamp {
|
||||
return 0, errors.New("clock moved backwards")
|
||||
}
|
||||
|
||||
if now == s.timestamp {
|
||||
s.sequence = (s.sequence + 1) & maxSequence
|
||||
if s.sequence == 0 {
|
||||
for now <= s.timestamp {
|
||||
now = time.Now().UnixMilli()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s.sequence = 0
|
||||
}
|
||||
|
||||
s.timestamp = now
|
||||
|
||||
id := ((now - epoch) << timestampLeftShift) |
|
||||
(s.datacenterId << datacenterIdShift) |
|
||||
(s.workerId << workerIdShift) |
|
||||
s.sequence
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (s *Snowflake) NextIDs(count int) ([]int64, error) {
|
||||
if count <= 0 || count > 1000 {
|
||||
return nil, errors.New("count must be between 1 and 1000")
|
||||
}
|
||||
|
||||
ids := make([]int64, count)
|
||||
for i := 0; i < count; i++ {
|
||||
id, err := s.NextID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ids[i] = id
|
||||
}
|
||||
|
||||
return ids, nil
|
||||
}
|
||||
Reference in New Issue
Block a user