雪花算法单线程实现-scala
/**
* [时间戳][数据标识id][机器id]
*/
object SnowFlake {
// 开始时间(ms) 2023-08-01 00:00:00
private val startTimestamp = 1690819200000L
// 机器id所占的位数
private val workerIdBits = 5L
// 数据标识id所占的位数
private val datacenterIdBits = 5L
// 支持的最大机器id
private val maxWorkerId = -1L ^ (-1L << workerIdBits)
// 支持的最大数据标识id
private val maxDatacenterId = -1L ^ (-1L << datacenterIdBits)
// 序列在id中占的位数
private val sequenceBits = 12L
// 机器id左移位数
private val workerIdShift = sequenceBits
// 数据标识id向左移位
private val datacenterIdShift = sequenceBits + workerIdBits
// 时间截向左移
private val timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits
// 生成序列的掩码
private val sequenceMask = -1L ^ (-1L << sequenceBits)
// 毫秒内序列
private var sequence = 0L
// 上次生成ID的时间截
private var lastTimestamp = -1L
def apply(
workerId: Long, // 工作机器id
datacenterId: Long // 数据中心id
): Long = {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(s"workerId=[$maxWorkerId] 数据范围错误")
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(s"datacenterId=[$maxDatacenterId] 数据范围错误")
}
var timestamp: Long = timeGen()
if (timestamp < lastTimestamp) {
throw new RuntimeException("当前时间小于上一次记录的时间戳")
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & sequenceMask
if (sequence == 0L) {
timestamp = tilNextMillis(lastTimestamp)
}
} else {
sequence = 0L
}
lastTimestamp = timestamp
// 时间戳 | 数据中心 | 机器标识 | 序列号
((timestamp - startTimestamp) << timestampLeftShift) |(datacenterId << datacenterIdShift) |(workerId << workerIdShift) | sequence
}
private def timeGen() : Long = {
System.currentTimeMillis()
}
private def tilNextMillis(lastTimestamp: Long): Long = {
var timestamp: Long = timeGen()
while (timestamp <= lastTimestamp) {
timestamp = timeGen()
}
timestamp
}
def main(args: Array[String]): Unit = {
for (_ <- 1 to 10) {
val id: Long = SnowFlake(1L, 1L)
println(id)
}
}
}
标签:val,sequence,单线程,timestamp,scala,lastTimestamp,private,算法,id
From: https://www.cnblogs.com/jentreywang/p/17649706.html