This is a snowflake-id service implemented by golang
A distributed monotone incremented Identifier generate algorithm
timestamp | shardId | seqId |
---|---|---|
timestamp difference in millisecond(41bit) | shardId(10bit) | seqId(12bit) |
-
in 1 millisecond could generate 2^12 different id
-
if more than 2^12 request in 1 millisecond, this service will block this request
use golang mutex lock for generate seqId operation
type Shard struct {
mulock sync.Mutex
epoch int64
lastTime int64
shardId int64
seqId int64
}
first get current timestamp
check current == lastTime then mean in same millisecond, then increase seqId
if current == lastTime and seqId > seqMax then mean need to wait until next millisecond
current > lastTime mean recount the seqId to 0
func (s *Shard) NextID() int64 {
s.mulock.Lock()
defer s.mulock.Unlock()
now := currentMillisecond()
if s.lastTime == now {
s.seqId++
// seqId over the max , then loop until next millisecond
if s.seqId > seqIdMax {
for now <= s.lastTime {
now = currentMillisecond()
}
}
} else {
s.seqId = 0
s.lastTime = now
}
id := int64((now-s.epoch)<<int64(timeShift) | (s.shardId << int64(shardShift)) | s.seqId)
return id
}
go run test -v ./... --race
go test -benchmem -run=none -bench ^BenchmarkTest$ github.com/yuanyu90221/go-snowflake-id-service/test --race