funcInitIDWorker(workerId, datacenterId int64) (*IDWorker, error) { //检查参数合法性 if workerId > maxWorkerId || workerId < 0 { var err = errors.New(fmt.Sprintf("worker Id can't be greater than %d or less than 0", maxWorkerId)) returnnil, err } if datacenterId > maxDatacenterId || datacenterId < 0 { var err = errors.New(fmt.Sprintf("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)) returnnil, err } fmt.Printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId) return &IDWorker{ datacenterId: datacenterId, workerId: workerId, }, nil }
/* 下一个ID生成算法 */ func(i *IDWorker) NextId() (id int64, err error) { //上锁 mutex.Lock() //程序结束 释放锁 defer mutex.Unlock() //先获取当前系统时间 var timestamp = timeGen() //如果当前系统时间比上次获取id时间戳小就抛出异常 时钟往后移动可能会出现同样id所以这里必须抛异常结束执行 if timestamp < lastTimestamp { fmt.Printf("clock is moving backwards. Rejecting requests until %d.", lastTimestamp) err = errors.New(fmt.Sprintf("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp-timestamp)) } //获取当前时间戳如果等于上次时间戳(同一毫秒内),则在序列号加一,否则序列号赋值为0, 从零开始 if timestamp == lastTimestamp { //这是使用&sequenceMask是为了防止sequence溢出12位(前面要求了sequence的长度只能是12位) i.sequence = (i.sequence + 1) & sequenceMask //如果防止刚好移除经过&sequenceMask后 会变成0 可能会发生重复的情况 //所以此时需要再次获取时间戳,并于上次时间戳作比较 直到与上次时间戳不一致返回当前时间戳避免重复 if i.sequence == 0 { timestamp = tilNextMillis(lastTimestamp) } } else { //如果不在同一个时间戳中 代表该序列刚开始计数所以初始为0 i.sequence = 0 } //将上次时间戳值更新 lastTimestamp = timestamp