订单号 雪花算法java,分布式id生成-雪花算法(SnowFlake)实现

分布式id生成-雪花算法(SnowFlake)实现

分布式id生成-雪花算法(SnowFlake)实现

1 雪花算法原理

SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图:

8c45ee8310d6df9183f1bda7a195d8bd.png

1bit,不用,二进制中最高位是符号位,0表示正数,固定是0

41bit,毫秒时间戳,2^41-1毫秒时间戳表示可使用69年

10bit,工作机器id,前5位表示机房id,后5位表示机器id,最大支持2^5 * 2^5=1024个机器

12bit,序列号,表示同一机器同一时间戳内可以产生的4096个ID序号

2 算法实现(java)

package com.demo.utils;

/**

* @author huwenlong

* @version 1.0

* @date 2020/9/17 8:40 下午

*/

public class SnowFlake {

/**

* 时间偏移量,从2020-09-17 20:41:42开始算起

*/

private final long twepoch = 1600346502216L;

/**

* 时间戳偏移量

*/

private final int timestampOffset = 22;

/**

* 机房id

*/

private final long datacenterId;

/**

* 机房id偏移量

*/

private final int datacenterIdOffset = 17;

/**

* 机器id

*/

private final long workerId;

/**

* 机器id偏移量

*/

private final int workerIdOffset = 12;

/**

* 当前序号

*/

private long currentSequence = 0L;

/**

* 最大序号

*/

private final int maxSequence = 4095;

/**

* 最后一次生成id的时间

*/

private long lastTimestamp = 0L;

public SnowFlake(long datacenterId, long workerId) {

this.datacenterId = datacenterId;

this.workerId = workerId;

}

public synchronized long nextId() {

long timestamp = System.currentTimeMillis();

if (timestamp < lastTimestamp) {

// 时钟回调抛异常

throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",

lastTimestamp - timestamp));

}

if (lastTimestamp == timestamp) {

// 如果同一毫秒内生成id则currentSequence自增

currentSequence = (currentSequence + 1) & maxSequence;

if (currentSequence == 0) {

//当某一毫秒的时间,产生的id数 超过4095,系统会进入等待,直到下一毫秒,系统继续产生ID

timestamp = tilNextMillis(lastTimestamp);

}

} else {

// 进入下一毫秒,从0开始

currentSequence = 0;

}

// 更新lastTimestamp

lastTimestamp = timestamp;

return ((timestamp - twepoch) << timestampOffset) | (datacenterId << datacenterIdOffset) | (workerId << workerIdOffset) | currentSequence;

}

private long tilNextMillis(long lastTimestamp) {

long timestamp = System.currentTimeMillis();

while (timestamp <= lastTimestamp) {

timestamp = System.currentTimeMillis();

}

return timestamp;

}

}

3 算法测试

public static void main(String[] args) {

SnowFlake snowFlake = new SnowFlake(1, 1);

for (int i = 0; i < 10; i++) {

System.out.println(snowFlake.nextId());

}

}

输出

13181447704576

13181451898880

13181451898881

13181451898882

13181451898883

13181451898884

13181451898885

13181451898886

13181451898887

13181451898888

public static void main(String[] args) {

SnowFlake snowFlake = new SnowFlake(1, 1);

Set set = new HashSet<>(10000);

for (int i = 0; i < 3000000; i++) {

set.add(snowFlake.nextId());

}

Assert.isTrue(set.size() == 3000000, "error");

}

public static void main(String[] args) {

SnowFlake snowFlake = new SnowFlake(1, 1);

long startTime = System.currentTimeMillis();

for (int i = 0; i < 3000000; i++) {

snowFlake.nextId();

}

System.out.println("cost:" + (System.currentTimeMillis() - startTime));

}

输出:cost:734,300w个id仅需要734ms,效率还是不错的

分布式id生成-雪花算法(SnowFlake)实现相关教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值