雪花算法(snowflake)是一种生成唯一id的分布式算法,由twitter推出。它能生成不重复的、有时间顺序的全局唯一id。一个典型的snowflake id由64位组成,通常划分如下:
- 1位符号位(始终为0,表示正数)
- 41位时间戳(毫秒级,表示当前时间相对于某个开始时间的偏移)
- 10位机器标识(通常分为数据中心id和机器id)
- 12位序列号(表示毫秒内的计数器)
下面是一个自定义的雪花算法来生成唯一的id。这个实现类似于twitter的snowflake算法,并考虑到了线程安全。
public class snowflakeidgenerator {
// 起始时间戳(2020-01-01 00:00:00)
private final long twepoch = 1577836800000l;
// 每部分占用的位数
private final long workeridbits = 5l;
private final long datacenteridbits = 5l;
private final long sequencebits = 12l;
// 最大值
private final long maxworkerid = -1l ^ (-1l << workeridbits);
private final long maxdatacenterid = -1l ^ (-1l << datacenteridbits);
// 位移
private final long workeridshift = sequencebits;
private final long datacenteridshift = sequencebits + workeridbits;
private final long timestampleftshift = sequencebits + workeridbits + datacenteridbits;
// 掩码
private final long sequencemask = -1l ^ (-1l << sequencebits);
private long workerid;
private long datacenterid;
private long sequence = 0l;
private long lasttimestamp = -1l;
public snowflakeidgenerator(long workerid, long datacenterid) {
if (workerid > maxworkerid || workerid < 0) {
throw new illegalargumentexception(string.format("worker id can't be greater than %d or less than 0", maxworkerid));
}
if (datacenterid > maxdatacenterid || datacenterid < 0) {
throw new illegalargumentexception(string.format("datacenter id can't be greater than %d or less than 0", maxdatacenterid));
}
this.workerid = workerid;
this.datacenterid = datacenterid;
}
public synchronized long nextid() {
long timestamp = timegen();
if (timestamp < lasttimestamp) {
throw new runtimeexception(string.format("clock moved backwards. refusing to generate id for %d milliseconds", lasttimestamp - timestamp));
}
if (lasttimestamp == timestamp) {
sequence = (sequence + 1) & sequencemask;
if (sequence == 0) {
timestamp = tilnextmillis(lasttimestamp);
}
} else {
sequence = 0l;
}
lasttimestamp = timestamp;
return ((timestamp - twepoch) << timestampleftshift)
| (datacenterid << datacenteridshift)
| (workerid << workeridshift)
| sequence;
}
protected long tilnextmillis(long lasttimestamp) {
long timestamp = timegen();
while (timestamp <= lasttimestamp) {
timestamp = timegen();
}
return timestamp;
}
protected long timegen() {
return system.currenttimemillis();
}
public static void main(string[] args) {
snowflakeidgenerator generator = new snowflakeidgenerator(1, 1);
for (int i = 0; i < 10; i++) {
system.out.println(generator.nextid());
}
}
}
说明
初始化参数:
twepoch:自定义的起始时间戳(可以是任意过去的时间),确保生成的id是唯一且有序的。workeridbits和datacenteridbits:分别表示工作节点id和数据中心id的位数(通常为5位)。sequencebits:表示序列号的位数(通常为12位)。
最大值计算:
maxworkerid和maxdatacenterid:根据位数计算出的最大值,确保id在合理范围内。
位移量:
workeridshift,datacenteridshift,timestampleftshift:用于将各部分数据移到正确的位置。
掩码:
sequencemask:确保序列号在0到4095之间循环。
方法:
nextid:生成唯一id,使用同步块确保线程安全。tilnextmillis:等待直到下一毫秒。timegen:获取当前时间戳。
使用示例
运行上述代码,你会看到生成的唯一id,它们是按时间顺序递增的,每个id包含了时间戳、数据中心id、工作节点id和序列号的信息。
到此这篇关于springboot自定义雪花算法生成id的实现示例的文章就介绍到这了,更多相关springboot 雪花算法生成id内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论