首页 > 编程语言 >Twitter的分布式自增ID雪花算法snowflake (Java版)

Twitter的分布式自增ID雪花算法snowflake (Java版)

时间:2022-12-08 16:03:40浏览次数:46  
标签:自增 Java Twitter private final datacenterId static long ID


分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。

有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。

而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序ID生成机制,所以开发了这样一套全局唯一ID生成服务。

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

Twitter的分布式自增ID雪花算法snowflake (Java版)_序列号

package com.example.demo.Utils.DistributedUtils;

/**
* 描述: Twitter的分布式自增ID雪花算法snowflake (Java版)
*/
public class SnowFlake {

/**
* 起始的时间戳
*/
private final static long START_STMP = 1480166465631L;

/**
* 每一部分占用的位数
*/
private final static long SEQUENCE_BIT = 12; //序列号占用的位数
private final static long MACHINE_BIT = 5; //机器标识占用的位数
private final static long DATACENTER_BIT = 5;//数据中心占用的位数

/**
* 每一部分的最大值
*/
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);

/**
* 每一部分向左的位移
*/
private final static long MACHINE_LEFT = SEQUENCE_BIT;
private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;

private long datacenterId; //数据中心
private long machineId; //机器标识
private long sequence = 0L; //序列号
private long lastStmp = -1L;//上一次时间戳

public SnowFlake(long datacenterId, long machineId) {
if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
}
if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
}
this.datacenterId = datacenterId;
this.machineId = machineId;
}

/**
* 产生下一个ID
*
* @return
*/
public synchronized long nextId() {
long currStmp = getNewstmp();
if (currStmp < lastStmp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}

if (currStmp == lastStmp) {
//相同毫秒内,序列号自增
sequence = (sequence + 1) & MAX_SEQUENCE;
//同一毫秒的序列数已经达到最大
if (sequence == 0L) {
currStmp = getNextMill();
}
} else {
//不同毫秒内,序列号置为0
sequence = 0L;
}

lastStmp = currStmp;

return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
| datacenterId << DATACENTER_LEFT //数据中心部分
| machineId << MACHINE_LEFT //机器标识部分
| sequence; //序列号部分
}

private long getNextMill() {
long mill = getNewstmp();
while (mill <= lastStmp) {
mill = getNewstmp();
}
return mill;
}

private long getNewstmp() {
return System.currentTimeMillis();
}

public static void main(String[] args) {
SnowFlake snowFlake = new SnowFlake(2, 3);

long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
System.out.println(snowFlake.nextId());
}

System.out.println(System.currentTimeMillis() - start);


}
}

snowflake生成的ID整体上按照时间自增排序,所有生成的id按时间趋势递增
整个分布式系统内不会产生重复id(因为有datacenterId和workerId来做区分)


标签:自增,Java,Twitter,private,final,datacenterId,static,long,ID
From: https://blog.51cto.com/u_15906694/5922610

相关文章

  • Java 8 Stream实现菜单树工具类
    TreeUtils:packagecom.ruoyi.common.core.utils.GuavaUtils.TreeUtils;importcom.alibaba.fastjson.JSON;importjava.util.Arrays;importjava.util.List;importjava.uti......
  • javascript-代码随想录训练营day15
    226.翻转二叉树题目链接:https://leetcode.cn/problems/invert-binary-tree/题目描述:给你一棵二叉树的根节点root,翻转这棵二叉树,并返回其根节点。输入:root=[4,2,7,......
  • 随笔(四)『Java多线程(创建线程方式)』
    1、创建线程方式一:『继承Thread类』/***创建线程方式一:『继承Thread类』*/publicclassThreadTest{publicstaticclassMyThreadextendsThread{......
  • Java单例模式的最佳实践?
    “读过书,……我便考你一考。茴香豆的茴字,怎样写的?”——鲁迅《孔乙己》0x00大纲目录0x00大纲0x01前言0x02单例的正确性new关键字clone方法克隆反序列化反射0x03最......
  • javascript-代码随想录训练营day14
    递归的三要素:递归函数的参数和返回值单层递归的逻辑终止条件144.二叉树的先序遍历题目链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/题目描......
  • (java 实现开箱即用基于 redis 的分布式锁
    项目简介lock为java设计的分布式锁,开箱即用,纵享丝滑。开源地址:https://github.com/houbb/lock目的开箱即用,支持注解式和过程式调用基于redis的分布式锁内......
  • java 大文件分片上传处理
    ​ 我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。这次项目的需求:支持大文件的上传和续传,要求续传支持......
  • Where is the “Father of Java?”
    Thisarticlewasoriginallypostedby ​​TylerHamilton​​ inthe ​​Toronto Star​​.Itisn’toftenthatweremembertheoriginatorsofideasandprod......
  • Java自学之路
    JAVA自学之路一:学会选择为了就业,不少同学参加各种各样的培训。 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机、嵌入式、游戏、3G、测试等。那么究竟应该选......
  • 使用JavaHTTPClient发送请求
    importorg.apache.http.Header;importorg.apache.http.HttpEntity;importorg.apache.http.HttpHeaders;importorg.apache.http.client.config.RequestConfig;impo......