Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrClockDriftTryLater and ErrClockDriftTooLargeToRecover both indicate the client to retry and hopefully the retry will land on a different worker. ErrClockDriftTryLater = errors.New("clock drift. try later") ErrClockDriftTooLargeToRecover = errors.New("clock drift too large to cover") // ErrNotReady indicates the worker is not in ready state: either in starting state or stopped state. ErrNotReady = errors.New("worker is not ready to serve request") )
Functions ¶
This section is empty.
Types ¶
type Generator ¶
type Generator struct {
// contains filtered or unexported fields
}
Generator generates snowflake id. Warning: Generator struct contains a mutex. Thus, it is not safe to copy Generator.
func NewGenerator ¶
NewGenerator returns a generator if the worker id is less than 1024.
func (*Generator) LastUsedTimestamp ¶
LastUsedTimestamp returns the last timestamp used to generate snowflake ID.
func (*Generator) Next ¶
Next returns snowflake ID and clock drift. In the case of clock drift, the returned snowflake ID is 0.
The snowflake id is a 64-bits long integer. bit 1 (most significant bit): set to 0, indicate this is a positive number. bit 2-42: Unix epoch timestamp in millis. bit 43-52: 10 bits to represent the worker ID. The worker id uniquely identify a process that generates Snowflake ID. bit 53-64: 12 bits. Sequence numbers. Each millisecond, there are 4096 IDs.
func (*Generator) SetLastUsedTimestamp ¶
SetLastUsedTimestamp sets the last timestamp used to generate snowflake ID.
type Worker ¶
type Worker struct {
// contains filtered or unexported fields
}
Worker coordinates through etcd to generate snowflake IDs.
- Coordinate through etcd to join and leave a cluster of workers. 1.1. At any point in time, no two workers have the same worker ID. 1.2. If a worker leaves the cluster and the worker ID is reused later, the timestamp associated with the worker ID must be monotonic increasing. Therefore, workers periodically uploads its timestamp to etcd.
2. Generate snowflake ID.
func NewWorker ¶
func NewWorker(endpoints []string, prefix, username, password string, maxWorkerCnt int) (*Worker, error)
NewWorker creates a new worker and adds the worker to a cluster.
func (*Worker) NextID ¶
NextID returns a snowflake ID. To avoid duplicate snowflake IDs, the timestamp in milliseconds must be monotonically increasing. The timestamp used here is the wall-clock time. If timestamp goes backward, we call it a wall-clock drift. In Go, if two consecutive time.Now() returns t1 and t2 respectively, the following statements are true. 1. t1 is always before t2. That means, t2.Before(t1) is true, and t2.Sub(t1) is positive. This is because time.Time is monotonic since 1.9. See [issue-12914](https://go.googlesource.com/proposal/+/master/design/12914-monotonic.md). 2. t2.UnixMilli() is larger than t1.UnixMilli() in most cases. But in cases of wall clock going backwards, t2.UnixMilli() < t1.UnixMilli(). For example, positive leap seconds, NTP adjustment, or the worker's clock is reset to a previous datetime.
We categorize the clock-drift in 3 buckets and handle them accordingly. bucket 1: [0, maxClockDriftToBlockInMillis): block by the drift time and return success. bucket 2: [maxClockDriftToBlockInMillis, maxClockDriftToReturnErrorInMillis]: return error (try later) immediately. We expect clients retry request on a different worker. bucket 3: [maxClockDriftToReturnErrorInMillis, infinity): something is wrong, we return error (try later) and remove the worker from the cluster. We recommend setting maxClockDriftToBlockInMillis to some value between 1 second and 2 seconds. That should avoid where all workers have a short clock drift (e.g. leap second) and client retries double the requests.
func (*Worker) Stop ¶
func (s *Worker) Stop()
Stop stops the worker. This is public method so that it can be called, e.g. called by the main thread on app exit.
func (*Worker) StopChannel ¶
func (s *Worker) StopChannel() <-chan struct{}
StopChannel returns a channel that notifies when the worker has stopped.