java中主键_Twitter-Snowflake主键算法Java实现

这一篇理论的东西就不解释了,直接上代码,有兴趣的可以看简书上另一篇文章:数据库分库分表(一)常见分布式主键ID生成策略

package util;

/**

* Twitter-snowflake负载均衡主键算法

* 共分成4段:

* 1.符号位( 1bit)

* 2.时间戳(41bit):计算下来能够使用的期限为:2039-09-07 23:47:35.551,如果希望支持更久,将参考时间1970-01-01换成其它时间

* 3.主机号(10bit):

* 4.序列号(12bit):1毫秒内单机的并发最大为4096,超过4096则只能等待下一毫秒

*/

public class SnowflakeGenerator {

//时间戳二进制位数

// private final static int TIMESTAMP_BITS = 41;

//主机号二进制位数

private final static int SERVER_NODE_BITS = 10;

//序列号二进制位数

private final static int SEQUENCE_BITS = 12;

//主机号:0~2**10-1

private final static int MAX_SERVER_NODE = 1024;

//序列号:0~2**12-1

private final static int MAX_SEQUENCE = 4096;

//当前主机节点[0,1024)

private static int serverNode = 0;

//序列号

private static int sequence = 0;

//上次生成id的时间

private static long previousTimestamp = -1L;

/**

* 生成唯一主键

* @return 64位long类型主键

*/

public static synchronized long generate(int node){

//初始化Snowflake主键生成器

if (node < 0 || node >= MAX_SERVER_NODE) {

throw new IllegalArgumentException(String.format("主机节点号范围为[%s and %s)", 0, MAX_SERVER_NODE));

}

serverNode = node;

long timestamp;

timestamp = System.currentTimeMillis();

if(timestamp>previousTimestamp){

sequence=0;

previousTimestamp=timestamp;

}else if(timestamp==previousTimestamp){

if(++sequence==MAX_SEQUENCE){

//序列号已到最大值,重置为0,此毫秒内不能再生成id,只能等下一毫秒

sequence=0;

timestamp=nextMillisecond();

previousTimestamp=timestamp;

}

}else{

throw new RuntimeException(String.format("当前时间戳 %s 小于 上次时间戳 %s",timestamp,previousTimestamp));

}

return timestamp<

//Java中的整型在计算机中是以二进制补码的形式存储的,最后这里需要了解补码及位运算的概念,位运算速度比十进制计算快很多

//[参考教程] http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

}

/**

* 等待,直到下一毫秒

* @return nextMillisecond

*/

private static long nextMillisecond() {

long nextMillisecond = System.currentTimeMillis();

while (nextMillisecond <= previousTimestamp) {

nextMillisecond = System.currentTimeMillis();

}

return nextMillisecond;

}

public static void main(String[] args) {

long start = System.currentTimeMillis();

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

long l = SnowflakeGenerator.generate(1023);

if(i==0 || i==1000000-1){

System.out.println(l);

}

}

long end = System.currentTimeMillis();

long diff = end - start;

System.out.println("用时:"+diff+"毫秒");

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值