理解分布式id生成算法--雪花算法(SnowFlake)

分布式ID生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。

注:

1B就是1个字节。
Byte、KB、B、MB、GB之间的关系是:
Bit——比特 ; B ——字节;KB——千字节;MB——兆字节;GB——吉字节;TB——太字节
1bit=0.125b ;1B=8 Bit   ;1KB=1024B      1MB=1024KB;1GB=1024MB;1TB=1024GB

 

1位,不用。二进制中最高位为1的都是负数,但是我们生成的ID一般都使用整数,所以这个最高位固定是0.

41位,用来记录时间戳(毫秒)

            41位可以表示正整数(计算机中整数包含0),可以表示的数值范围是:0至$2^{41}-1$,

            减1是因为可表示的的数值范围是从0开始算的,而不是1.

             也就是说41位可以表示$2^{41}-1$个毫秒的值,转化成单位年则是$2^({41}-1)/(1000*60*60*24*365)=69$年

10位,用来记录工作机器ID。

         可以部署在$2^{10}=1024$个字节。包括5位datacenterId和5位workerId。

          5位(bit)可以表示的最大正整数是$2^{5}-1=31$,即可以用0,1,2,3....31这32个数字,来表示不同的datacenterId 

          或者workerId.

12位,序列号,用来记录同毫秒内产生的不同Id。

        12位(bit)可以表示的最大整数是$2^{12}-1=4095$,即可以用0、1、2、3....4094这4095个数字,来表示同一机器

         同一时间戳(毫秒)内产生的4095个ID序号。

由于在java中64bit的整数是long类型,所以在java中SnowFlake算法生产的ID就是longKauai存储的,

 

SnowFlake可以保证:

所有生成ID按时间趋势递增。

整个分布式系统内不会产生重复ID(因为datacenterID和wokerID来做区分)

 

 

java代码工具类:

 

package suanfa;

/**
* ### 雪花算法:
SnowFlake算法用来生成64位的ID,刚好可以用long整型存储,能够用于分布式系统中生产唯一的ID, 并且生成的ID有大致的顺序。 在这次实现中,生成的64位ID可以分成5个部分:

`0 - 41位时间戳 - 5位数据中心标识 - 5位机器标识 - 12位序列号`

````java
* twitter的snowflake算法 -- java实现
*
* @author beyond
* @date 2016/11/26
*/
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;//数据中心占用的位数

/**
* 每一部分的最大值
*/
//最大支持数据中心节点数0~31,一共32个
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
//最大支持机器节点数0~31,一共32个
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
//序列号0~12,一共12个
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);

/**
* 每一部分向左的位移
*/
//机器节点左移12位
private final static long MACHINE_LEFT = SEQUENCE_BIT;
//数据中心节点左移17位
private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
//时间毫秒数左移22位
private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;

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

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) {
//数据中心id,机器标识id
SnowFlake snowFlake = new SnowFlake(2, 3);
System.out.println(snowFlake.nextId());

}

}

 

转载于:https://www.cnblogs.com/javaDB2019/p/10935854.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[ZJOI2010]贪吃的老鼠

P2570 [ZJOI2010]贪吃的老鼠 在Ta的博客查看 显然二分&#xff0c;最大流判定 要满足两个条件&#xff1a; (1) 在任一时刻&#xff0c;一只老鼠最多可以吃一块奶酪&#xff1b; (2) 在任一时刻&#xff0c;一块奶酪最多被一只老鼠吃。 先按照奶酪的边界进行离散化&#xff0c…

IP: 169.254.0.0/16 地址用途

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 一直困惑169.254.0.0/16是干嘛的&#xff0c;每次笔记本dhcp获取地址失败后&#xff0c;就会随机在这个B类地址段获取一个地址&#…

值得借鉴的30条好习惯

我有幸一直能生活在比较好的圈子中&#xff0c;我的优秀的同学、舍友&#xff0c;乃至我现在创业后遇到的优秀创业者&#xff0c;从他们身上看到和学到一些好的习惯。 我一直觉得&#xff0c;好的习惯&#xff0c;是成功和进步的重要一点。我随手总结一些给大家&#xff0c;零散…

【PKUSC2019】线弦图【计数】【树形DP】【分治FFT】

Description 定义线图为把无向图的边变成点&#xff0c;新图中点与点之间右边当且仅当它们对应的边在原图中有公共点&#xff0c;这样得到的图。 定义弦图为不存在一个长度大于3的纯环&#xff0c;纯环的定义是在环上任取两个不相邻的点&#xff0c;它们之间都没有边&#xff0…

注解 @PostConstruct 与 @PreDestroy 详解及实例

简介 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Java EE5 引入了PostConstruct和PreDestroy这两个作用于Servlet生命周期的注解&#xff0c;实现Bean初始化之前和销毁之前的自定义操…

别让6种不良心理偷走你的好人缘

众所周知&#xff0c;拥有正常、健康的交际圈对于人的身心健康都是很有帮助的。但是若想维系好自己的交际圈&#xff0c;也是很不容易的&#xff0c;甚至在不经意间产生的某些心理&#xff0c;就会直接给大家的人际交往带来影响。那么接下来&#xff0c;小编就先为大家归纳一下…

PHP 安装xdebug

xdebug官网: https://xdebug.org 安装步骤如下: 使用 phpinfo() 打印出PHP相关信息, 全选, 复制 打开 xdebug 网站: https://xdebug.org/wizard.php 在图中输入框中粘贴你复制的信息, 点击 Analyse my phpinfo() output 在结果中点击下载, 然后按照它提示的步骤进行操作即可…

apt-clone:备份已安装的软件包并在新的 Ubuntu 系统上恢复它们

当我们在基于 Ubuntu/Debian 的系统上使用 apt-clone&#xff0c;包安装会变得更加容易。如果你需要在少量系统上安装相同的软件包时&#xff0c;apt-clone 会适合你。 如果你想在每个系统上手动构建和安装必要的软件包&#xff0c;这是一个耗时的过程。它可以通过多种方式实现…

分布式消息中间件 : Rocketmq

简述 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 分布式消息中间件&#xff0c;主要是实现分布式系统中解耦、异步消息、流量销锋、日志处理等场景。生产中用的最多的消息队…

PV、UV、UIP、VV、CPC、CPM、RPM、CTR指的是什么?

PV(PageView)&#xff1a;网站浏览量&#xff0c;指页面的浏览次数&#xff0c;用以衡量网站用户访问的网页数量。用户没打开一个页面便记录1次PV&#xff0c;多次打开同一页面则浏览量累计&#xff1b;UV(UniqueVistor)&#xff1a;独立访客数&#xff0c;指1天内访问某站点的…

linux opencl(AMD) Example

最近对并行计算很感兴趣。不过搞MPI对我来说暂时没什么用&#xff0c;基于GPU的并行计算倒是挺实用。网上的资料都是CUDA的。实质上我对CUDA一点兴趣都没有。无论别人的架构多么先进&#xff0c;我这个只有AMD显卡的小孩都是旁观者而已。在这里记录一下一个opencl程序的编译过程…

php使用supervisor管理进程脚本

supervisor是用python开发的一个在linux系统下的进程管理工具&#xff0c;可以方便的监听&#xff0c;启动&#xff0c;停止一个或多个进程。当一个进程被意外杀死后&#xff0c;supervisor监听到后&#xff0c;会自动重新拉起进程。 一、supervisor的安装 1、通过easy_install…

重写规则和重载规则

重写规则&#xff1a; 发生在有继承关系的类之间&#xff08;同一类就是重载了&#xff09;相同的方法名&#xff0c;参数列表&#xff0c;返回类型可见性&#xff08;public,protected,private&#xff09;不能被缩小异常不能被放大规则与c中不一样静态类型不能被重写方法重载…

消息中间件:RocketMQ 介绍(特性、术语、原理、优缺点、消息顺序、消息重复)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 消息中间件的作用 1. 应用解耦 2. 异步处理 比如用户注册场景&#xff0c;注册主流程完成以后&#xff0c;需要调用邮件系统发送邮件…

C# JsonHelper类

记录一下&#xff0c;方便下次用。 public class JsonHelper{#region Json/// <summary>/// JavaScriptSerializer/// </summary>/// <typeparam name"T"></typeparam>/// <param name"obj"></param>/// <returns&…

[译】Redux入门教程(一)

前言 老外写技术文章真是叼&#xff0c;这是国外的一个程序员写的一个简单易懂,循序渐进的Redux教程&#xff0c;本着共享的精神&#xff0c;就翻译出来给大家一起看&#xff0c;文章最后有链接&#xff0c;不想看我翻译的直接去看原文吧。 下面是原教程的英文目录 这篇先更三分…

使用 Intellij Idea 打包 java 工程为可执行 jar 包

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 其实还有个简单多了方法&#xff0c;见&#xff1a; 超简单方法&#xff1a; Intellij Idea 把 java 工程打成可运行的 jar 步骤&#x…

QuickStart系列:docker部署之Gitlab本地代码仓库

gitlab是可以在本地搭建的使用git作为源代码管理的仓库。 运行环境&#xff1a; win10vmware14docker7docker 1. 使用命令拉取镜像&#xff08;非必须&#xff0c;耗时比较久&#xff0c;这里以ce为准&#xff0c;ce是社区版&#xff0c;ee是企业版&#xff09;&#xff1a; do…

超简单方法: Intellij Idea 把 java 工程打成可运行的 jar

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 找到 Intellij Idea 最下面的 Terminal 选项&#xff0c;并点击进入该界面。 2. 在光标位置输入命令&#xff1a;mvn clean 。清理…

LDAP-轻量级目录访问协议(统一认证)

概念 LDAP是轻量目录访问协议&#xff0c;英文全称是Lightweight Directory Access Protocol&#xff0c;一般都简称为LDAP。 参考资料 LDAP概念和原理介绍 我花了一个五一终于搞懂了OpenLDAP LDAP-Apache Directory Studio使用&#xff08;创建DC.OU及用户&#xff09; 转载于…