开箱即用轻量级雪花算法id生成器Java工具类

开箱即用轻量级雪花算法id生成器Java工具类

    • 1.1 背景
    • 1.2 雪花算法id生成器Java工具类

1.1 背景

在 Java后端研发过程中,对于分布式微服务来说,一般需要分布式 id生成.

这里分享一个非常好用且大多数情况下都可用的开箱即用轻量级雪花算法id生成器Java工具类。

这种方式生成的雪花算法生成器生成的唯一主键id,好处是不依赖第三方组件,轻量级,缺点是服务器的时钟不可以回拨,否则可能会造成生成的主键id冲突。

1.2 雪花算法id生成器Java工具类

雪花算法id生成器Java工具类源码

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;/*** id自增器(雪花算法)* @author renjie* @version 1.0.0*/
public class SnowFlakeUtils {private final static long twepoch = 12888349746579L;/*** 机器标识位数*/private final static long workerIdBits = 5L;/*** 数据中心标识位数*/private final static long datacenterIdBits = 5L;/*** 毫秒内自增位数*/private final static long sequenceBits = 12L;/*** 机器ID偏左移12位*/private final static long workerIdShift = sequenceBits;/*** 数据中心ID左移17位*/private final static long datacenterIdShift = sequenceBits + workerIdBits;/*** 时间毫秒左移22位*/private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;/*** sequence掩码,确保sequnce不会超出上限*/private final static long sequenceMask = -1L ^ (-1L << sequenceBits);/*** 上次时间戳*/private static long lastTimestamp = -1L;/*** 序列*/private long sequence = 0L;/*** 服务器ID*/private long workerId = 1L;private static long workerMask = -1L ^ (-1L << workerIdBits);/*** 进程编码*/private long processId = 1L;private static long processMask = -1L ^ (-1L << datacenterIdBits);private static SnowFlakeUtils snowFlakeUtils = null;static{snowFlakeUtils = new SnowFlakeUtils();}public static synchronized long nextId(){return snowFlakeUtils.getNextId();}private SnowFlakeUtils() {//获取机器编码this.workerId=this.getMachineNum();//获取进程编码RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();this.processId=Long.valueOf(runtimeMXBean.getName().split("@")[0]).longValue();//避免编码超出最大值this.workerId=workerId & workerMask;this.processId=processId & processMask;}public synchronized long getNextId() {//获取时间戳long timestamp = timeGen();//如果时间戳小于上次时间戳则报错if (timestamp < lastTimestamp) {try {throw new Exception("Clock moved backwards.  Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds");} catch (Exception e) {e.printStackTrace();}}//如果时间戳与上次时间戳相同if (lastTimestamp == timestamp) {// 当前毫秒内,则+1,与sequenceMask确保sequence不会超出上限sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {// 当前毫秒内计数满了,则等待下一秒timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0;}lastTimestamp = timestamp;// ID偏移组合生成最终的ID,并返回IDlong nextId = ((timestamp - twepoch) << timestampLeftShift) | (processId << datacenterIdShift) | (workerId << workerIdShift) | sequence;return nextId;}/*** 再次获取时间戳直到获取的时间戳与现有的不同* @param lastTimestamp* @return 下一个时间戳*/private long tilNextMillis(final long lastTimestamp) {long timestamp = this.timeGen();while (timestamp <= lastTimestamp) {timestamp = this.timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}/*** 获取机器编码* @return*/private long getMachineNum(){long machinePiece;StringBuilder sb = new StringBuilder();Enumeration<NetworkInterface> e = null;try {e = NetworkInterface.getNetworkInterfaces();} catch (SocketException e1) {e1.printStackTrace();}while (e.hasMoreElements()) {NetworkInterface ni = e.nextElement();sb.append(ni.toString());}machinePiece = sb.toString().hashCode();return machinePiece;}
}

注意事项
这个雪花算法实现是一个常见的分布式唯一ID生成器,但它也有一些潜在的问题和优化空间:

  • 唯一性保证
    • 该算法的唯一性依赖于每个节点的机器ID(workerId)和数据中心ID(processId)。如果这些ID在不同节点上配置不正确,可能导致ID冲突。
    • 唯一性还依赖于时钟同步。如果时钟回拨(Clock Drift)或不稳定,可能会导致生成的ID不唯一。
  • 时钟回拨问题:
    • 该算法没有显式处理时钟回拨情况。如果系统时钟发生回拨,可能会导致生成的ID不连续,甚至出现重复。
    • 优化:您可以考虑在时钟回拨检测到时采取适当的措施,例如等待或重新生成ID。
  • 长期运行问题
    • 如果您的应用长期运行,可能会达到每毫秒生成的ID数量的限制,尤其是在高并发情况下。
    • 优化:可以根据实际需求调整位数,以提高每毫秒生成ID的上限。
  • 可扩展性问题
    • 该算法中的位数分配不一定适用于所有应用。如果您的应用需要更多的数据中心或机器节点,需要重新分配位数。
    • 优化:可以根据需求增加位数分配的灵活性,以支持更多的数据中心或机器。
  • 不适用于移动设备:
    • 该算法依赖于机器ID和数据中心ID的配置,对于移动设备等无法确定唯一ID的环境不适用。
    • 优化:可以考虑在这种情况下使用其他唯一ID生成策略。
  • 异常处理
    • 该算法在出现异常情况时没有提供良好的处理机制,例如时钟回拨异常。
    • 优化:添加适当的异常处理,以确保生成的ID在异常情况下也是正确的。
  • 总的来说,这个雪花算法实现在大多数情况下都能正常工作,但在特定情况下可能会出现问题。
  • 优化的策略会根据应用的具体需求而变化,可以根据需要进行调整,以确保生成的ID满足唯一性、连续性和性能要求。
  • 如果您需要更高级的解决方案,还可以考虑使用分布式ID生成服务或其他专用工具。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

证书显示未受信任,生成的证书过期

此时若是导入证书后&#xff0c;证书显示未受信任&#xff0c;则说明我们缺失最新的AppleWWDRCA证书 解决方案&#xff1a; 重新下载AppleWWDRCA并安装。即下载最新的AppleWWDRCA证书&#xff0c;双击安装到“登录”项的钥匙串下&#xff1b;然后再安装你的开发证书或者发布证书…

WebSocket实战之六心跳重连机制

一、前言 WebSocket应用部署到生产环境&#xff0c;我们除了会碰到因为经过代理服务器无法连接的问题&#xff08;注&#xff1a;该问题可以通过搭建WSS来解决&#xff0c;具体配置请看 WebSocket实战之四WSS配置 &#xff09;&#xff0c;另外一个问题就是外网环境不稳定经常…

Appium开发

特点 开源免费支持多个平台 IOS(苹果)、安卓App的自动化都支持 支持多种类型的自动化 支持苹果、安卓应用原生界面的自动化支持应用内嵌网络视图的自动化支持手机浏览器(Chrome)中的web网站自动化支持flutter应用的自动化 支持多种编程语言 像selenium一样&#xff0c;可以用多…

react.js在visual code 下的hello World

想学习reacr.js &#xff0c;就开始做一个hello world。 我的环境是visual code &#xff0c;所以我找这个环境下的例子。参照&#xff1a; https://code.visualstudio.com/docs/nodejs/reactjs-tutorial 要学习react.js &#xff0c;还得先安装node.js&#xff0c;我在visual …

面试打底稿④ 专业技能的第四部分

简历原文 抽查部分 了解Python的使用&#xff08;第一篇关于Python升级版本bug解决的文章斩获6W阅读&#xff09;&#xff0c;用python实现了几篇图像信息隐藏领 域论文的复现&#xff08;博客中有提及&#xff09;&#xff1b; 了解Django基本框架&#xff0c;写过Django框架的…

【软考】4.2 关系代数

《 关系代数 》 表和表之间的逻辑运算 笛卡尔积&#xff1a;S1 x S2 投影&#xff1a;π&#xff1b;选择某一列&#xff08;属性&#xff09;&#xff1b;一个关系R的投影操作结果也是一个关系&#xff0c;记作Πa&#xff0c;它由从关系R中选出的A列元素构成&#xff1b;选择…

测开 | Vue速查知识点

文章目录 Vue知识1. Vue 概述2. Vue 代码格式3. Vue 指令3.1 v-bind & v-model3.2 v-on3.3 v-if和v-show3.4 v-for 4. 生命周期 Vue知识 1. Vue 概述 简介&#xff1a; Vue.js&#xff08;读音 /vjuː/, 类似于 view&#xff09; 是一套构建用户界面的 渐进式框架。与其他…

CodeCraft-21 and Codeforces Round 711 (Div. 2)A-F

1.Problem - A - Codeforces &#xff08;1&#xff09;题意 求一个大于等于n的整数x&#xff0c;满足gcd(x,sum(dig(x)) > 1&#xff0c;dig表示x的各个数位。 &#xff08;2&#xff09;思路 考虑最差是满足gcd(x,sum(dig(x)) 2,因此不会枚举很多&#xff0c;直接暴力枚…

Webpack 基础入门以及接入 CSS、Typescript、Babel

一、什么是 Webpack Webpack 是一款 JS 模块化开发的技术框架&#xff0c;其运作原理是将多个 JS 文件关联起来构成可运行的应用程序。 Webpack 拥有丰富的 plugins / loaders 插件生态圈&#xff0c;可以让 js 识别不同的语言如 .css, .scss, .sass, .json, .xml, .ts, .vue…

数据结构:复杂度分析

目录 1 算法效率评估 1.1 实际测试 1.2 理论估算 2 迭代与递归 2.1 迭代 1. for 循环 2. while 循环 3. 嵌套循环 2.2 递归 1. 调用栈 2. 尾递归 3. 递归树 2.3 两者对比 3 时间复杂度 3.1 统计时间增长趋势 3.2 函数渐近上界…

c++的io流

文章目录 1.C语言的输入和输出2.流失是什么3.cIO流3.1c标准io流3.2c文件io流 4.stringstream的简单介绍 1.C语言的输入和输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()&#xff0c;scanf(): 从标准输入设备(键盘)读取数据&#xff0c;并将值存放在变量中…

学信息系统项目管理师第4版系列16_资源管理过程

1. 组建项目团队&#xff0c;建设项目团队和管理项目团队属于执行过程组 1.1. 【高22上选21】 1.1.1. 【高21上选25】 1.2. 3版 2. 【高19上案三】 2.1. 【高18上案三】 2.2. 【高23上案一】 3. 规划资源管理 3.1. 定义如何估算、获取、管理和利用团队以及实物资源的过…

lv7 嵌入式开发-网络编程开发 04 IP地址与端口号

目录 1 IP地址 1.1 IP 地址及其表示方法 1.2 分类的 IP 地址 1.3 无分类编址 CIDR 1.3.1 网络前缀 1.3.2 地址块 1.3.3 地址掩码 (address mask) 1.4 IPv6 的地址 1.4.1 表示方式 1.4.2 零压缩 2 端口号 2.1 进程之间的通信 2.2 运输层的作用 2.3 屏蔽作用 2.4…

C#中的for和foreach的探究与学习

一:语句及表示方法 for语句: for(初始表达式;条件表达式;增量表达式) {循环体 }foreach语句: foreach(数据类型 变量 in 数组或集合) {循环体 }理解 1.从程序逻辑上理解,foreach是通过指针偏移实现的(最初在-1位置,每循环一次,指针就便宜一个单位),而for循环是通

十二、【漏洞复现】Rails任意文件读取(CVE-2019-5418)

十二、【漏洞复现】Rails任意文件读取(CVE-2019-5418&#xff09; 12.1、漏洞原理 Ruby on Rails是一个使用 Ruby 语言写的开源 Web 应用框架&#xff0c;它是严格按照 MVC 结构开发的。它努力使自身保持简单&#xff0c;来使实际的应用开发时的代码更少&#xff0c;使用最少…

下载盗版网站视频并将.ts视频文件合并

. 1.分析视频请求123 2.数据获取和拼接 1.分析视频请求 1 通过抓包观察我们发现视频是由.ts文件拼接成的每一个.ts文件代表一小段2 通过观察0.ts和1.ts的url我们发现他们只有最后一段不同我们网上找到url获取的包3 我们发现index.m3u8中储存着所有的.ts文件名在拼接上前面固定…

数据结构 1.1 初学数据结构

数据结构的基本概念 数据结构在学什么&#xff1f; 如何用程序代码把现实世界的问题信息化 如何用计算机高效处理信息从而创造价值 数据&#xff1a; 数据元素、数据项&#xff1a; 数据元素——描述一个个体 数据对象——数据元素之间具有同样的性质 同一个数据对象里的数…

kubernetes集群kubeadm方式安装

测试网络和DNS解析 kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh ping www.baidu,com nslookup kubernetes.default.svc.cluster.localbusybox要用指定的1.28版本,不能用最新版本,最新版本,nslookup会解析不到dns和ip 延长kubernetes…

linux命令行配置音频设备

linux命令行配置音频设备 TLTR在linux命令行播放音乐cmus需要开始声音条件功能才能调节播放的音量&#xff0c;看这个链接&#xff0c;继续折腾&#xff0c;have fun! TLTR 以archLinux为例&#xff0c;把下面软件都装一遍。 sudo pacman -S alsa-utils sudo pacman -S alsa-…

数据结构—栈、队列、链表

一、栈 Stack&#xff08;存取O(1)&#xff09; 先进后出&#xff0c;进去123&#xff0c;出来321。 基于数组&#xff1a;最后一位为栈尾&#xff0c;用于取操作。 基于链表&#xff1a;第一位为栈尾&#xff0c;用于取操作。 1.1、数组栈 /*** 基于数组实现的顺序栈&#…