// 假设sequence溢出则变为0,阐明1毫秒内并发作成的ID数量超过了4096个,这个时分同1毫秒的第4097个生成的ID必须等候下一毫秒
if (sequence == 0) {
// 死循环等候下一个毫秒值,直到比lastTimestamp大
timestamp = tilNextMillis(lastTimestamp)
}
} else {
// 低并发场景,不同毫秒中生成ID
// 不同毫秒的状况下,由于外层办法保证了timestamp大于或许小于lastTimestamp,而小于的状况是发作了时钟回拨,下面会抛出异常,所以不用思索
// 也就是只需求思索一种状况:timestamp > lastTimestamp,也就是以后生成的ID所在的毫秒数比上一个ID大
// 所以假设时间戳部分增大,可以确定整数值一定变大,所以序列号其实可以不用计算,这里直接赋值为0
sequence = 0
}
// 获取到的时间戳比上一个保存的时间戳小,阐明时钟回拨,这种状况下直接抛出异常,拒绝生成ID
// 团体以为,这个办法应该可以提早到var timestamp = timeGen()这段代码之后
if (timestamp < lastTimestamp) {
exceptionCounter.incr(1)
log.error("clock is moving backwards. Rejecting requests until %d.", lastTimestamp);
throw new InvalidSystemClock("Clock moved backwards. Refusing to generate id for %d milliseconds".format(lastTimestamp - timestamp));
}
// lastTimestamp保存以后时间戳,作为办法下次被调用的上一个时间戳的快照
lastTimestamp = timestamp
// 度量统计,生成的ID计数器加1
genCounter.incr()
// X = (系统时间戳 - 自定义的纪元值) 然后左移22位
// Y = (数据中心ID左移17位)
// Z = (机器ID左移12位)
// 最后ID = X | Y | Z | 计算出来的序列号sequence
((timestamp - twepoch) << timestampLeftShift) |
(datacenterId << datacenterIdShift) |
(workerId << workerIdShift) |
sequence
}
// 辅佐办法:获取系统以后的时间戳(毫秒)
protected def timeGen(): Long = System.currentTimeMillis()
// 辅佐办法:获取系统以后的时间戳(毫秒),用死循环保证比传入的lastTimestamp大,也就是获取下一个比lastTimestamp大的毫秒数
protected def tilNextMillis(lastTimestamp: Long): Long = {
var timestamp = timeGen()
while (timestamp <= lastTimestamp) {
timestamp = timeGen()
}
timestamp
}
(责任编辑:admin)