Twitter的分布式自增ID雪花算法snowflake

Twitter的分布式自增ID雪花算法snowflake

  • 一、Twitter的分布式自增ID雪花算法snowflake
  • endl

一、Twitter的分布式自增ID雪花算法snowflake

/*** Twitter的分布式自增ID雪花算法snowflake* SnowFlake的结构如下(每部分用-分开):* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。* 41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号* 加起来刚好64位,为一个Long型。* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高。* 经测试,SnowFlake每秒能够产生26万ID左右。*/
public class SnowFlake {// 因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0/*** 起始的时间戳*/private static final long START_STMP = 1480166465631L;/*** 每一部分占用的位数*/private static final long SEQUENCE_BIT = 12; // 序列号占用的位数private static final long MACHINE_BIT = 5; // 机器标识占用的位数private static final long DATACENTER_BIT = 5; // 数据中心占用的位数/*** 每一部分的最大值*/// 这个是一个意思,就是5 bit最多只能有31个数字,机房id最多只能是32以内private static final long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);// 这个是二进制运算,就是5 bit最多只能有31个数字,也就是说机器id最多只能是32以内private static final long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);// 每毫秒内产生的id数 2 的 12次方private static final long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);/*** 每一部分向左的位移*/private static final long MACHINE_LEFT = SEQUENCE_BIT;private static final long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;private static final long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;// 机房ID 2进制5位  32位减掉1位 31个private long datacenterId; // 数据中心、机房ID// 机器ID  2进制5位  32位减掉1位 31个private long machineId; // 机器标识// 代表一毫秒内生成的多个id的最新序号  12位 4096 -1 = 4095 个private long sequence = 0L; // 序列号// 记录产生时间毫秒数,判断是否是同1毫秒private long lastTimestamp = -1L; // 上一次时间戳public SnowFlake(long datacenterId, long machineId) {// 检查机房id和机器id是否超过31 不能小于0if (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;}/*** 这个是核心方法,通过调用nextId()方法,让当前这台机器上的snowflake算法程序生成一个全局唯一的id*/public synchronized long nextId() {long currentTimestamp = getNewsTimestamp();if (currentTimestamp < lastTimestamp) {throw new RuntimeException("Clock moved backwards.  Refusing to generate id");}// 下面是说假设在同一个毫秒内,又发送了一个请求生成一个id// 这个时候就得把seqence序号给递增1,最多就是4096if (currentTimestamp == lastTimestamp) {// 这个意思是说一个毫秒内最多只能有4096个数字,无论你传递多少进来,// 这个位运算保证始终就是在4096这个范围内,避免你自己传递个sequence超过了4096这个范围sequence = (sequence + 1) & MAX_SEQUENCE;// 当某一毫秒的时间,产生的id数 超过4095,系统会进入等待,直到下一毫秒,系统继续产生IDif (sequence == 0L) {currentTimestamp = getNextMill();}} else {// 不同毫秒内,序列号置为0sequence = 0L;}lastTimestamp = currentTimestamp;// 最核心的二进制位运算操作,生成一个64bit的id// 先将当前时间戳左移,放到41 bit那儿;将机房id左移放到5 bit那儿;将机器id左移放到5 bit那儿;将序号放最后12 bit// 最后拼接起来成一个64 bit的二进制数字,转换成10进制就是个long型return (currentTimestamp - START_STMP) << TIMESTMP_LEFT // 时间戳部分| datacenterId << DATACENTER_LEFT // 数据中心部分| machineId << MACHINE_LEFT // 机器标识部分| sequence; // 序列号部分}/*** 阻塞到下一个毫秒,直到获得新的时间戳* lastTimestamp 上次生成ID的时间截* @return 当前时间戳*/private long getNextMill() {long mill = getNewsTimestamp();while (mill <= lastTimestamp) {mill = getNewsTimestamp();}return mill;}/*** 返回以毫秒为单位的当前时间* @return 当前时间(毫秒)*/private long getNewsTimestamp() {return System.currentTimeMillis();}public static void main(String[] args) {SnowFlake snowFlake = new SnowFlake(2, 3);long start = System.currentTimeMillis();for (int i = 0; i < 100000; i++) {System.out.println("当前生成的有序数字串 : " + (snowFlake.nextId()));}System.out.println("总耗时 : " + (System.currentTimeMillis() - start));System.out.println("MAX_MACHINE_NUM : " + MAX_MACHINE_NUM);System.out.println("MAX_DATACENTER_NUM : " + MAX_DATACENTER_NUM);System.out.println("MAX_SEQUENCE : " + MAX_SEQUENCE);}
}

endl

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

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

相关文章

外连接 (outer join)

外连接 (outer join) 左外连结 (left outer join) 右外连结 (right outer join) 全外连结 (full join) 内连接与外连接的区别 内连接操作在表关系的笛卡尔积中去掉了不匹配的数据记录&#xff0c;只输出满足连接条件的数据记录。 在连接语句中只写join&#xff0c;而不写是…

打破信息差,计算机专业必须知道的进大厂的方式

现在的信息茧房有多可怕&#xff0c;如果你提前知道这几个进大厂实习的方法&#xff0c;你将超越百分之九十的大学生。 一、高校就业指导中心 大学生们找实习可以从本校高校就业指导中心网站上找&#xff0c;这个渠道建议重点关注下&#xff0c;此类渠道推荐的实习机会&#…

B2B2C电商系统源代码部署,让你轻松开启网店生意

在当今数字化时代&#xff0c;开设一家网店已经变得异常简单。借助B2B2C电商系统源代码部署&#xff0c;你可以轻松搭建自己的在线商城&#xff0c;开始网店生意。这种系统为企业提供了一个强大的平台&#xff0c;让他们可以直接与制造商和消费者进行交易&#xff0c;从而实现品…

AcWing16. 替换空格

题目 请实现一个函数&#xff0c;把字符串中的每个空格替换成"%20"。 数据范围 0≤0≤ 输入字符串的长度 ≤1000≤1000。 注意输出字符串的长度可能大于 10001000。 样例 输入&#xff1a;"We are happy."输出&#xff1a;"We%20are%20hap…

ETL的数据挖掘方式

ETL的基本概念 数据抽取&#xff08;Extraction&#xff09;&#xff1a;从不同源头系统中获取所需数据的步骤。比如从mysql中拿取数据就是一种简单的抽取动作&#xff0c;从API接口拿取数据也是。 数据转换&#xff08;Transformation&#xff09;&#xff1a;清洗、整合和转…

WebGL开发数字孪生系统

使用WebGL开发数字孪生系统通常涉及以下步骤。WebGL是一种用于在浏览器中实现3D图形渲染的JavaScript API&#xff0c;它可以用于创建交互性强、高度可视化的数字孪生系统。 1.需求分析&#xff1a; 确定数字孪生系统的目标和用途。明确系统的功能需求、用户需求以及与物理实体…

高性能服务系列【六】网络的有效载荷

谈到高性能服务是很难绕开网络部分&#xff0c;毕竟单机时代早已过去。对于多节点构成的服务系统&#xff0c;要提高总体性能&#xff0c;除了单节点足够强悍外&#xff0c;节点之间的通讯代价是必须考虑的关键。我们在刚开始的章节&#xff0c;就谈到网卡和磁盘是挂接在低速南…

Java项目:46 ssm005基于SSM框架的购物商城系统+jsp(含文档)

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 项目是单体ssm电商水果平台&#xff0c;包括前台商城平台及后台管理系统 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流…

连接端口和连接端口转换OrCAD补丁

来介绍此功能之前先复习一下一些OrCAD的基础知识。 说到连通两个器件&#xff0c;有什么办法呢&#xff1f;最直接的就是用线连通。比如下面这两个器件需要连通&#xff0c;我们可以直接用线Place wire连接。 但是如果这两个器件由于某些原因&#xff0c;他们之间相隔很远&…

c# 使用 Oxyplot 创建和绘制 ContourSeries

我有一个 WPF 应用程序&#xff0c;我需要在其中可视化 y y(x1, x2)&#xff0c;其中 x1、x2 是线性坐标。我可以使用 Oxyplot 中的 HeatMapSeries 来做到这一点&#xff0c;但是当我想在同一窗口中绘制两组数据时&#xff0c;热图不是合适的工具。几个轮廓系列会更好。 现在&…

MS5583N高分辨率模数转换器

产品简述 MS5583N 是一款高分辨率模数转换器&#xff0c;内部集 成高阶 Σ-Δ 调制器、低噪声可编程增益放大器、多 路输入选择器和多种内部数字滤波器。其转换速率 从 250SPS 到 4kSPS 。此外&#xff0c;芯片内部集成失调校准 寄存器和增益校准寄存器。 MS5583N …

题目 2113: T1309-回文数

题目描述: 若一个数&#xff08;首位不为零&#xff09;从左向右读与从右向左读都是一样&#xff0c;我们就将其称之为回文数。例如&#xff1a;给定一个 10进制数 56&#xff0c;将 56加 65&#xff08;即把56从右向左读&#xff09;&#xff0c;得到 121是一个回文数。又如&…

haproxy-高性能负载均衡反向代理服务

目录 一、HAProxy&#xff08;High Availability Proxy&#xff09;概述 1、HAProxy的概念 2、HAProxy的主要特性 3、HAProxy的优缺点 4、Haproxy负载均衡策略 5、LVS、nginx、HAProxy的区别 二、安装HAProxy 1、yum安装 2、第三方rpm包安装 3、编译安装 3.1 解决 l…

流量分析-webshell管理工具

文章目录 CSCS的工作原理CS流量特征 菜刀phpJSPASP 蚁剑冰蝎哥斯拉 对于常见的webshell管理工具有中国菜刀&#xff0c;蚁剑&#xff0c;冰蝎&#xff0c;哥斯拉。同时还有渗透工具cobaltstrike(CS)。 CS CobaltStrike有控制端&#xff0c;被控端&#xff0c;服务端。(相当于黑…

day52 动态规划part13● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

考虑到一般动态规划的写法是n方&#xff0c;为了降低复杂度&#xff0c;考虑每次假如选择当前数dp[i]对应最长的序列&#xff0c;就找前面上一个数&#xff08;已经做递推的时候记录了上一个数的比他小的一个数&#xff0c;因为等于上一个比他小的数的序列长度&#xff08;已经…

寻找峰值(二分查找思想)

解法一&#xff1a;暴力求解 int findPeakElement(int* nums, int numsLen ) {// write code herefor (int i 1; i < numsLen - 1; i) {if ((nums[i] > nums[i - 1]) && (nums[i] > nums[i1])) {return i;}}if (nums[numsLen - 1] > nums[numsLen - 2]) …

ubuntu docker-compose 编排容器并且设置自启动

安装docker-compose sudo apt install docker-compose编写docker-compose.yml 这是我的docker-compose,里面写了5个容器&#xff0c;一个sqlserver的db&#xff0c;一个airlfow&#xff0c;一个我的主项目&#xff0c;会根据里面规定好的启动顺序启动。 version: "3.7&…

蓝桥杯练习系统(算法训练)ALGO-980 斐波那契串

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;10.0s Java时间限制&#xff1a;30.0s Python时间限制&#xff1a;50.0s 问题描述 斐波那契串由下列规则生成&#xff1a;   F[0] "0";   F[1] "1";   F[n] F[n-1] F[n-2]…

鸿蒙开发为什么这么火,现在入行鸿蒙是否来的及?

鸿蒙开发是当前备受关注的技术领域之一&#xff0c;对于想要入门学习鸿蒙开发的初学者来说&#xff0c;需要掌握一定的基础知识和技能。鸿蒙开发又是否能为程序员们带来一片光明的未来呢&#xff1f;让我们一同探讨这些问题。 对于初学者来说&#xff0c;鸿蒙开发是否易于上手呢…

MySQL基础-----多表关系与查询概述

目录 前言 一、多表关系 1.一对多 2.多对多 3.一对一 二、多表查询概述 1.概述 2.笛卡尔积 3.分类 前言 本期我们开始学习新的章节&#xff0c;也就是MySQL的多表关系与查询&#xff0c;在本期主要是讲述概念性的东西&#xff0c;大概介绍多表关系是什么&#xff0c;为什…