5 分布式ID

这里讲一个比较常用的分布式防重复的ID生成策略,雪花算法

一个用户体量比较大的分布式系统必然伴随着分表分库,分机房部署,单体的部署方式肯定是承载不了这么大的体量。

雪花算法的结构说明

如下图所示:
在这里插入图片描述

雪花算法组成

从上图我们可以看出来雪花算法是64bit位的long类型的数值型的id。其中由4部分组成。

1bit为固定为0,表明生成的id为正数。

41bit位毫秒级的时间戳(可保留69年的时间戳)

标识位为10位,由5位的机器id和5位的服务id组成。5bit位能标识32个数值,32*32=1024 共能表示1024个数值,也就是说我们部署的服务可以水平扩展至1024个实例部署。在国内的应用中基本上是够用了。

12位的序列号位,表示同一个实例在1毫秒内能生成4096个序列,基本上也是够用了。

如果按照水平扩展应用还不能够承载我们的体量,我们可以对上面的组成进行改造。比如我们一个应用实例不会在1毫秒生成4096个数值,我们可以把时间戳的值改成35位,把6个bit均分到机器id和服务id上,也就是说我们可以部署256*256=65536个实例。

雪花算法的具体实现代码如下:

/*** 雪花算法工具类* 64位long类型的= 第一位0表示为正数 + 1到41的时间戳 + 5位的数据中心id + 5位的机器id + 12位的序列号* @author yusong* @20241111*/
public class SnowflakeIdWorkerUtil {//开始时间戳 2025-01-01=1735660800000Lprivate final long startTime = 1731400000000L;//数据中心所占雪花算法数据的位数private final long datacenterIdBits = 5L;//机器号所占雪花算法的位数private final long workerIdBits = 5L;
//    //支持最大的数据中心 结果为31
//    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
//    //支持最大的机器编号 结果为31
//    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);//同一时间戳生成的序列号所占位数private final long sequenceBits = 12L;//机器号左移位数=序列号的位数 = 12private final long workerIdShift = sequenceBits;//数据中心左移位数= 序列号的位数 + 机器号的位数 = 17private final long datacenterIdShift = sequenceBits + workerIdBits;//时间戳左移位数= 序列号的位数 + 机器号的位数 + 数据中心位数 = 22private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;//生成序列号的最大数=4095private final long sequenceMask = -1L ^ (-1L << sequenceBits);//数据中心编号private long datacenterId;//机器号private long workerId;//毫秒内序列从0开始private long sequence = 0L;//上次生成ID的时间截private long lastTimestamp = -1L;private static SnowflakeIdWorkerUtil sw = null;/**** @param datacenterId 数据中心编号id* @param workerId           机器编号id* @return*/public static synchronized SnowflakeIdWorkerUtil getSnowflakeId(long datacenterId,long workerId) {if(datacenterId>31||datacenterId<0) {throw new RuntimeException("datacenterId必须是0到31位的整数");}if(workerId>31||workerId<0) {throw new RuntimeException("workerId必须是0到31位的整数");}if(sw==null) {sw = new SnowflakeIdWorkerUtil();sw.datacenterId = datacenterId;sw.workerId = workerId;}return sw;}/*** 私有的构造函数 防止外部new*/private SnowflakeIdWorkerUtil() {}/*** 获取下一个id* @return*/public synchronized long nextId() {long timestamp = timeGen();//如果当前时间戳小于上次的时间戳 说明系统时钟回退过 应该抛出异常if(timestamp<this.lastTimestamp) {throw new RuntimeException("系统时钟回退异常,请检查系统设置");}//如果是同一时间戳生成id,则进行毫秒内序列if(this.lastTimestamp==timestamp) {sequence = (sequence + 1) & sequenceMask;//同一毫秒内序列溢出 则等待下一秒if(sequence==0) {timestamp = nextMillis(lastTimestamp);}}else {sequence = 0L;}this.lastTimestamp = timestamp;return ((timestamp - startTime)<<timestampLeftShift)|(datacenterId<<datacenterIdShift)|(workerId<<workerIdShift)|sequence;}/*** 阻塞到下一毫秒,直到获取到新的时间戳* @param lastTimestamp* @return*/private long nextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}/*** 获取当前的时间戳* @return*/private long timeGen() {return System.currentTimeMillis();}public static void main(String[] args) {for(int i=0;i<100;i++) {SnowflakeIdWorkerUtil swu = SnowflakeIdWorkerUtil.getSnowflakeId(0, 0);long id = swu.nextId();System.out.println(Long.toBinaryString(id));System.out.println(id);}}}

雪花算法有个问题就是不能进行时钟回拨,如果进行时钟回拨就会生成重复的id。如果我们考虑以上问题可以在我们的程序中保留最近一次的生成时间,并拿来做校验,就可解决这个问题。办法总比问题多。

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

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

相关文章

怎么实现Redis的高可用?

大家好&#xff0c;我是锋哥。今天分享关于【怎么实现Redis的高可用&#xff1f;】面试题。希望对大家有帮助&#xff1b; 怎么实现Redis的高可用&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 为了实现 Redis 的高可用性&#xff0c;我们需要保证在发…

牛客网刷题 ——C语言初阶(6指针)——BC106 上三角矩阵判定

1. 题目描述——BC106 上三角矩阵判定 牛客网OJ题链接 描述 KiKi想知道一个n阶方矩是否为上三角矩阵&#xff0c;请帮他编程判定。上三角矩阵即主对角线以下的元素都为0的矩阵&#xff0c;主对角线为从矩阵的左上角至右下角的连线。 示例 输入&#xff1a; 3 1 2 3 0 4 5 0 0…

H266/VVC 帧内预测中 ISP 技术

帧内子划分 ISP ISP 技术是在 JVET-2002-v3 提案中详细介绍其原理&#xff0c;在 VTM8 中完整展示算法。ISP是线基内预测&#xff08;LIP&#xff09;模式的更新版本&#xff0c;它改善了原始方法在编码增益和复杂度之间的权衡&#xff0c;ISP 算法的核心原理就是利用较近的像…

了解npm:JavaScript包管理工具

在JavaScript的生态系统中&#xff0c;npm&#xff08;Node Package Manager&#xff09;无疑是一个举足轻重的存在。它不仅是Node.js的包管理器&#xff0c;更是前端开发不可或缺的一部分&#xff0c;为开发者提供了丰富的包资源、便捷的包管理以及强大的社区支持。本文将深入…

CNN Test Data

由于数据量过大&#xff0c;打不开了 搞一组小的吧。收工睡觉 https://download.csdn.net/download/spencer_tseng/90256048

自动化测试脚本实践:基于 Bash 的模块化测试框架

前言 在现代软件开发中&#xff0c;测试自动化是确保软件质量和稳定性的核心手段之一。随着开发周期的缩短和功能模块的增多&#xff0c;手动测试逐渐无法满足高效性和准确性的需求。因此&#xff0c;测试人员需要依赖自动化工具来提升测试效率&#xff0c;减少人为干预和错误。…

verilogHDL仿真详解

前言 Verilog HDL中提供了丰富的系统任务和系统函数&#xff0c;用于对仿真环境、文件操作、时间控制等进行操作。&#xff08;后续会进行补充&#xff09; 正文 一、verilogHDL仿真详解 timescale 1ns/1ps //时间单位为1ns&#xff0c;精度为1ps&#xff0c; //编译…

Nginx 配置支持 HTTPS 代理

个人博客地址&#xff1a;Nginx 配置支持 HTTPS 代理 | 一张假钞的真实世界 本文描述的是Nginx HTTPS反向代理的情况&#xff08;即后端服务是HTTP的&#xff09;。 使用openssl配置ssl证书 生成服务器端的私钥&#xff08;key 文件&#xff09;&#xff1a; # openssl gen…

协同过滤算法商品推荐系统|Java|SpringBoot|VUE|

【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、Maven、Mysql5.7 4⃣️&#xff1a;技术栈&#xff1a;Java、Mysql、SpringBoot、Mybatis-Plus、VUE、jquery,html 5⃣️…

初学stm32 --- DMA直接存储器

目录 DMA介绍 STM32F1 DMA框图 DMA处理过程 DMA通道 DMA优先级 DMA相关寄存器介绍 F1 DMA通道x配置寄存器&#xff08;DMA_CCRx&#xff09; DMA中断状态寄存器&#xff08;DMA_ISR&#xff09; DMA中断标志清除寄存器&#xff08;DMA_IFCR&#xff09; DMA通道x传输…

数据通过canal 同步es,存在延迟问题,解决方案

当使用 Canal 同步数据到 Elasticsearch&#xff08;ES&#xff09;时&#xff0c;出现延迟问题通常源于多个因素&#xff0c;如 Canal 配置、网络延迟、ES 的负载和性能瓶颈等。以下是一些解决方案&#xff0c;帮助减少和解决延迟问题&#xff1a; 1. 优化 Canal 配置 Canal…

javafx 将项目打包为 Windows 的可执行文件exe

要将 JavaFX 项目打包为 .exe 文件&#xff0c;你可以使用一些工具将你的应用程序封装为 Windows 可执行文件。以下是两种常用的方法&#xff1a; 方法 1&#xff1a;使用 jpackage&#xff08;适用于 JDK 14 及更高版本&#xff09; jpackage 是 JDK 内置的工具&#xff0c;…

SQL进阶实战技巧:即时订单比例问题

目录 0 需求描述 1 数据准备 2 问题分析 3 小结 往期精彩 0 需求描述 订单配送中,如果期望配送日期和下单日期相同,称为即时订单,如果期望配送日期和下单日期不同,称为计划订单。 请从配送信息表(delivery_info)中求出每个用户的首单(用户的第一个订单)中即时订单…

Routine Load 导入问题处理指南

Routine Load 导入问题处理指南 在使用 Apache Doris 的 Routine Load 时&#xff0c;你是否曾经被各种奇奇怪怪的问题卡住&#xff1f;今天就来分享一些最常见的 Routine Load 问题&#xff0c;并提供相应的解决方案&#xff0c;让你快速应对&#xff0c;高效解决&#xff01;…

【面试题】技术场景 6、Java 生产环境 bug 排查

生产环境 bug 排查思路 分析日志&#xff1a;首先通过分析日志查看是否存在错误信息&#xff0c;利用之前讲过的 elk 及查看日志的命令缩小查找错误范围&#xff0c;方便定位问题。远程 debug 适用环境&#xff1a;一般公司正式生产环境不允许远程 debug&#xff0c;多在测试环…

牛客 《反转链表》 链表 题解

前言 太久没有练习C和Java&#xff0c;基本忘完了…还有数据结构也不太熟悉了。借此机会回顾一下相关的知识点&#xff0c;也为之后做准备吧。 题目内容 思路 要求时间复杂度为O(n)&#xff0c;那么只能遍历一次。反转的话&#xff0c;只需要将链表箭头指向换个方向就行。遍…

容器技术全面攻略:Docker的硬核玩法

文章背景 想象一下&#xff0c;一个项目终于要上线了&#xff0c;结果因为环境配置不一致&#xff0c;测试服务器一切正常&#xff0c;生产环境却宕机了。这是开发者噩梦的开始&#xff0c;也是Docker救世主角色的登场&#xff01;Docker的出现颠覆了传统环境配置的方式&#…

RabbitMQ高级篇

目录 确保发送者的可靠 为什么需要确保发送者的可靠性 RabbitMQ 的发送者重连机制配置 springAMQP实现发送者确认 MQ的可靠性 为什么需要实现MQ的可靠性&#xff1f; 数据持久化 Lazy Queue 核心思想 总结RabbitMQ 如何保证消息的可靠性 持久化 Lazy Queue 消息…

微信小程序用的SSL证书有什么要求吗?

微信小程序主要建立在手机端使用&#xff0c;然而手机又涉及到各种系统及版本&#xff0c;所以对SSL证书也有要求&#xff0c;如果要小程序可以安全有效的访问需要满足以下要求&#xff1a; 1、原厂SSL证书&#xff08;原厂封&#xff09;。 2、DV单域名或者DV通配符。 3、兼…

OpenCV计算机视觉 07 图像的模块匹配

在做目标检测、图像识别时&#xff0c;我们经常用到模板匹配&#xff0c;以确定模板在输入图像中的可能位置 API函数 cv2.matchTemplate(image, templ, method, resultNone, maskNone) 参数含义&#xff1a; image&#xff1a;待搜索图像 templ&#xff1a;模板图像 method&…