分布式—雪花算法生成ID

news2024/9/24 9:22:59

一、简介

1、雪花算法的组成:

由64个Bit(比特)位组成的long类型的数字

0 | 0000000000 0000000000 0000000000 000000000 | 00000 | 00000 | 000000000000

1个bit:符号位,始终为0。
41个bit:时间戳,精确到毫秒级别,可以使用69年。
10个bit:工作机器ID,可以部署在1024个节点上。
12个bit:序列号,每个节点每毫秒内最多可以生成4096个ID。

2、雪花算法的优缺点

优点:

全局唯一:雪花算法生成的ID是全局唯一的,可以用于分布式系统中的数据分片和数据合并。
时间有序:雪花算法生成的ID中包含了时间戳信息,可以根据ID的大小推算出生成的时间。
高性能:雪花算法生成ID的速度很快,可以满足高并发的场景需求。
可扩展性:雪花算法的数据结构相对简单,易于扩展和修改。

缺点:

依赖于系统时钟:雪花算法生成ID的过程中依赖于系统时钟,如果系统时钟发生回拨,可能会导致生成的ID出现重复。
长度固定:雪花算法生成的ID长度固定为64位,可能会导致存储和传输成本较高。
不支持分布式计算:雪花算法生成ID的过程是单线程的,不能支持分布式计算。

二、项目中使用 

1、引入依赖 

<dependency>
    <groupId>com.github.beyondfengyu</groupId>
    <artifactId>snowflake-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

2、配置参数 

snowflake:
  data-center-id: 1 # 数据中心ID,可以使用机器IP地址最后一段数字,范围为0-31
  machine-id: 1 # 机器ID,可以使用服务器编号,范围为0-31

3、使用 

@Service
public class OrderSevice {

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
 
    public Long creatOrderId() {
        return snowflakeIdWorker.nextId();
    }
}

三、手写雪花算法生成ID


/**
 * 功能描述:雪花算法生成订单号
 */
public class SnowFlakeTemplate {

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

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

    //每一部分的最大值
    private final static long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_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 DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
    private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
    private long dataCenterId; //数据中心
    private long machineId; //机器标识
    private long sequence = 0L; //序列号
    private long lastStamp = -1L;//上一次时间戳

    public SnowFlakeTemplate(long dataCenterId, long machineId) {
        if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) {
            throw new IllegalArgumentException("dataCenterId can't be greaterthan MAX_DATA_CENTER_NUM or less than 0");
        }
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException("machineId can't be greater thanMAX_MACHINE_NUM or less than 0");
        }
        this.dataCenterId = dataCenterId;
        this.machineId = machineId;
    }

    private String Prefix() {
        String randomPrefix = "";
        for (int i = 0; i < 2; i++) {
            char c = (char) (Math.random() * 26 + 'A');
            randomPrefix += c;
        }
        return randomPrefix;
    }

    //产生下一个ID
    public synchronized String nextId() {
        long currStamp = getNewStamp();
        if (currStamp < lastStamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate id");
        }
        if (currStamp == lastStamp) {
            //相同毫秒内,序列号自增
            sequence = (sequence + 1) & MAX_SEQUENCE;
            //同一毫秒的序列数已经达到最大
            if (sequence == 0L) {
                currStamp = getNextMill();
            }
        } else {
            //不同毫秒内,序列号置为0
            sequence = 0L;
        }
        lastStamp = currStamp;
        return Prefix() + ((currStamp - START_STAMP) << TIMESTAMP_LEFT //时间戳部分
                | dataCenterId << DATA_CENTER_LEFT //数据中心部分
                | machineId << MACHINE_LEFT //机器标识部分
                | sequence); //序列号部分
    }

    private long getNextMill() {
        long mill = getNewStamp();
        while (mill <= lastStamp) {
            mill = getNewStamp();
        }
        return mill;
    }

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

    public static void main(String[] args) {
        System.out.println(new SnowFlakeTemplate(2, 3).nextId() );
    }
}

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

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

相关文章

Python slice(切片)

在Python中&#xff0c;切片(slice)是对序列型对象(如list, string, tuple)的一种高级索引方法。普通索引只取出序列中一个下标对应的元素&#xff0c;而切片取出序列中一个范围对应的元素&#xff0c;这里的范围不是狭义上的连续片段。 切片的基本语法为&#xff1a; object…

ChromeOS 的 Linux 操作系统和 Chrome 浏览器分离

导读科技媒体 Ars Technica 报道称&#xff0c;谷歌正在将 ChromeOS 的浏览器从操作系统中分离出来 —— 让它变得更像 Linux。虽然目前还没有任何官方消息&#xff0c;但这项变化可能会在本月的版本更新中推出。 据介绍&#xff0c;谷歌将该项目命名为 "Lacros"——…

防溺水预警识别系统算法

防溺水预警识别系统旨在通过opencvpython网络模型深度学习算法&#xff0c;防溺水预警识别系统算法实时监测河道环境&#xff0c;对学生等违规下水游泳等危险行为进行预警和提醒。Python是一种由Guido van Rossum开发的通用编程语言&#xff0c;它很快就变得非常流行&#xff0…

strcat函数

目录 函数介绍&#xff1a; 函数声明&#xff1a; 具体使用&#xff1a; 注意事项&#xff1a; 字符串⾃⼰给⾃⼰追加&#xff0c;如何&#xff1f; 模拟实现strcat函数&#xff1a; 函数介绍&#xff1a; 被称为字符串的追加/链接函数&#xff0c;它的功能就是在一个字符…

gcc/linux下的c++异常实现

概述 本文不一定具有很好的说教性&#xff0c;仅作为自我学习的笔记。不妨可参阅国外大神博文C exceptions under the hood链接中包含了大量的例子。 偶有在对ELF做分析的时候看到如下图一些注释&#xff0c;部分关键字看不懂&#xff0c;比如什么FDE, unwind , __gxx_perso…

【技巧分享】如何获取子窗体选择了多少记录数?一招搞定!

Hi,大家好久不见。 我这个更新速度是不是太慢了呀&#xff0c;因为&#xff0c;最近又又又在忙&#xff0c;请大家谅解啦。 现在更新文章、视频都要花好久去考虑&#xff0c;好不容易有个灵感了&#xff0c;一搜索&#xff0c;结果发现之前都已经分享过了&#xff08;委屈脸&…

Nginx详解 第三部分:Nginx高级配置(附配置实例)

Part 3 一、网页的状态页二、Nginx第三方模块2.1 echo 模块 三、变量3.1 内置变量3.1.1 常用内置变量3.1.2 举个例子 3.2 自定义变量 四、自定义访问日志 (优化)4.1 自定义访问日志的格式4.2 自定义json 格式日志 五、Nginx压缩功能&#xff08;重要&#xff09;六、HTTPS 功能…

SMC_Interpolator2Dir反向插补运动

附加函数是&#xff1a; SMC_Interpolator2Dir_SlowTask 函数的位置&#xff1a; 输入&#xff1a; 运行 bExecute 【BOOL】 路径包 poqDataIn 指向SMC_OUTQUEUE的指针 停止 bSlow_Stop 停止BOOL 急停 bEmergency_Stop 紧急停止BOOL 单…

2023.8 - java - 多态

多态是同一个行为具有多个不同表现形式或形态的能力。 多态就是同一个接口&#xff0c;使用不同的实例而执行不同操作&#xff0c; 多态的优点 1. 可替换性2 可扩充性3. 接口性、灵活性、简化性4. 消除类型之间的耦合关系 多态存在的三个必要条件 继承重写父类引用指向子类…

Java“牵手”天猫商品历史价格信息API接口数据,天猫API接口申请指南

天猫平台商品历史价格接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取天猫商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片、最低价、当前价格、价格信息等详细信息 。 获取商品历史价格接口API是一种用于获取电商平台…

如何运行imbalanced-streams-master工程?

1 下载和安装JDK和Eclipse 这个步骤网上的教程特别多&#xff0c;在此就不特别叙述了。 2 将imbalanced-streams-master工程解压并引入 2.1 解压 特别要注意的是&#xff1a;解压的文件夹和workspace一定不要在同一个目录。 解压后的目录结构如下&#xff1a; 2.2 import…

图片换脸-->>视频换脸-->>直播换脸

资源网站&#xff1a;https://tianfeng.space/ 个人娱乐&#xff0c;切勿作恶 下载 ​ 网盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1DHMY1mCXpT0OtpmlvIoMKA 提取码&#xff1a;nf57 使用 下载解压后&#xff0c;打开 第一个就是你要替换的人脸&#xff0c;…

学习率调整策略

学习率是可以控制更新的步伐的。 我们在训练模型的时候&#xff0c;一般开始的时候学习率会比较大&#xff0c;这样可以以一个比较快的速度到达最优点的附近&#xff0c;然后再把学习率降下来&#xff0c; 缓慢的去收敛到最优值。学习率前期要大&#xff0c;后期要小 在学习学…

生成对抗网络(GAN):在图像生成和修复中的应用

文章目录 什么是生成对抗网络&#xff08;GAN&#xff09;&#xff1f;GAN在图像生成中的应用图像生成风格迁移 GAN在图像修复中的应用图像修复 拓展应用领域总结 &#x1f389;欢迎来到AIGC人工智能专栏~生成对抗网络&#xff08;GAN&#xff09;&#xff1a;在图像生成和修复…

PCI/PCIE总线的宏观理解

1、pcie总线协议实现的效果 (1)像访问内存一样去访问外设&#xff1b; (2)当建立好CPU地址空间到PCI/PCIE地址空间的映射关系后&#xff0c;程序访问CPU地址空间就可以达到访问PCI/PCIE地址空间的效果&#xff1b; 2、芯片地址空间 (1)32位的CPU寻址范围是4G&#xff0c;64位的…

【算法训练-链表】反转链表、区间反转链表、K个一组反转链表

从今天开始进行高频算法的训练&#xff0c;一方面训练自己的逻辑思维&#xff0c;一方面保持自己的竞争力。训练过程有这么两个基准原则&#xff1a; 首先训练题的来源呢有三个&#xff0c;首选的是三个都出现过的高频题&#xff0c;以&#xff1a;牛客101为基准分类&#xff…

渗透测试工具ZAP入门教程(2)-HUD教程

平视显示器 HUD是一种全新的与ZAP进行交互的方式。 它将安全信息叠加到你正在测试的应用程序上&#xff0c;并允许你访问关键的ZAP功能。 对于刚接触安全的人来说&#xff0c;它更易于理解&#xff0c;但同时也允许经验丰富的渗透测试人员将重点放在他们正在测试的应用程序上。…

计算机网络(速率、宽带、吞吐量、时延、发送时延)

速率&#xff1a; 最重要的一个性能指标。 指的是数据的传送速率&#xff0c;也称为数据率 (data rate) 或比特率 (bit rate)。 单位&#xff1a;bit/s&#xff0c;或 kbit/s、Mbit/s、 Gbit/s 等。 例如 4 1010 bit/s 的数据率就记为 40 Gbit/s。 速率往往是指额定速率或…

图床项目进度(二)——动态酷炫首页

前言&#xff1a; 前面的文章我不是说我简单copy了站友的一个登录页吗&#xff0c;我感觉还是太单调了&#xff0c;想加一个好看的背景。 但是我前端的水平哪里够啊&#xff0c;于是在网上找了找制作动态背景的插件。 效果如下图。 如何使用 这个插件是particles.js 安装…

vue2 自定义指令,插槽

一、学习目标 1.自定义指令 基本语法&#xff08;全局、局部注册&#xff09;指令的值v-loading的指令封装 2.插槽 默认插槽具名插槽作用域插槽 二、自定义指令 1.指令介绍 内置指令&#xff1a;v-html、v-if、v-bind、v-on… 这都是Vue给咱们内置的一些指令&#xff0c;…