雪花算法生成全局Id,看这篇就够了

news2024/12/25 23:44:02

分布式id

  • 雪花算法能够生成一个64位long类型数据,适合做分布式系统的全局标识符,或者分库分表中,同类型数据表的主键

原理探究

  • 雪花算法:以一台服务器为对象,在一毫秒时间内,生成一个自增的long数据
  • 特点:雪花算法生成的id具有唯一性,和实时性

下面,就来研究一下,雪花id是如何保证全局唯一的

组成

划重点:一位符号位,41位时间毫秒数,10位机器id,12位同毫秒自增序号,共64位
在这里插入图片描述
由此,我们可以分析得出以下结论:

  • 时间戳位于高位,且时间戳随时间递增,所以,雪花id随时间递增
  • 10位机器id,一共可以为2^10=1024台服务器生成id
  • 12位序列号,即在1毫秒内,可以生成2^12=4096个id,换句话说,就是雪花id最高支持409 万的每秒并发量
  • 雪花id是否会重复,取决于时间戳是否重复,也就是说,当服务器调回过去的时间时,就会导致雪花id不再唯一

生成过程

/**
 * 雪花算法生成id
 */
public class SnowFlakeClient {

    /**
     * 起始时间戳
     */
    private static final long START_TIMESTAMP = 1704038400L; //2024-01-01 00:00:00

    /**
     * 各组成部分占用的位数
     * */
    /**
     * 时间戳
     */
    private static final long TIMESTAMP_BIT = 41;

    /**
     * 机器id
     */
    private static final long MACHINE_BIT = 10;

    /**
     * 序列号
     */
    private static final long SEQUENCE_BIT = 12;

    // 每一部分的最大值
    private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
    private static final long MAX_MACHINE_NUM = ~(-1L << MACHINE_BIT);

    // 每一部分向左的位移
    private static final long MACHINE_LEFT = SEQUENCE_BIT;
    private static final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;


    /**
     * 上一次生成id的时间戳(不断改变)
     */
    private static long lastTimeStamp = -1L;

    /**
     * 递增序列号
     */
    private static long sequence = 0L;

    /**
     * 生成雪花id
     */
    public static long nextId() {

        //1.获取当前时间戳
        long now = System.currentTimeMillis();

        //2.判断服务器是否时钟回拨
        if (now < lastTimeStamp) {
            throw new RuntimeException("服务器时钟回拨,可能会导致id不唯一");
        }

        //3.判断是否在同一毫秒
        if (now == lastTimeStamp) {
            //3.1同一毫秒内,就让序列号递增,注意不要超出最大范围
            sequence = (sequence + 1) & MAX_SEQUENCE;//做与运算就能去掉超出最高位的数字
            if (sequence == 0L) {
                //3.1.1序列号已经用完了,本毫秒内不再生成新id
                now = System.currentTimeMillis();
                while (now <= lastTimeStamp) {
                    now = System.currentTimeMillis();
                }
            }
        } else {
            //不在同一个毫秒,重置序列号
            sequence = 0L;
        }

        //更新时间戳
        lastTimeStamp = now;

        //4.组合成id:使用移位,以及或运算
        long id = ((now - START_TIMESTAMP) << TIMESTAMP_LEFT) | (IdConfig.machineId << MACHINE_LEFT) | sequence;

        return id;

    }

}

测试:

public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Long.toBinaryString(SnowFlakeClient.nextId()));
        }
    }
}

结果:

110001110111110101001000111111101111111100000000000000000000000
110001110111110101001000111111110001001010000000000000000000000
110001110111110101001000111111110001001010000000000000000000001
110001110111110101001000111111110001001010000000000000000000010
110001110111110101001000111111110001001010000000000000000000011
110001110111110101001000111111110001001010000000000000000000100
110001110111110101001000111111110001001010000000000000000000101
110001110111110101001000111111110001001010000000000000000000110
110001110111110101001000111111110001001010000000000000000000111
110001110111110101001000111111110001001010000000000000000001000
110001110111110101001000111111110001001010000000000000000001001
110001110111110101001000111111110001001010000000000000000001010
110001110111110101001000111111110001001100000000000000000000000
110001110111110101001000111111110001001100000000000000000000001
110001110111110101001000111111110001001100000000000000000000010
110001110111110101001000111111110001001100000000000000000000011
110001110111110101001000111111110001001100000000000000000000100
110001110111110101001000111111110001001100000000000000000000101
110001110111110101001000111111110001001100000000000000000000110
110001110111110101001000111111110001001100000000000000000000111
110001110111110101001000111111110001001100000000000000000001000
110001110111110101001000111111110001001100000000000000000001001
110001110111110101001000111111110001001100000000000000000001010
110001110111110101001000111111110001001100000000000000000001011
110001110111110101001000111111110001001100000000000000000001100
110001110111110101001000111111110001001100000000000000000001101
110001110111110101001000111111110001001100000000000000000001110
在这里插入代码片

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

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

相关文章

Ps 滤镜:视频

Ps菜单&#xff1a;滤镜/视频 Filter/Video “视频”滤镜子菜单中包含了“NTSC 颜色”和“逐行”两个滤镜。 这两个滤镜都是针对视频和电视播放的特定需求设计的。 “逐行”滤镜主要解决交错视频的视觉问题&#xff0c;而“NTSC 颜色”滤镜则确保色彩在电视播放时的兼容性和准确…

springboot+vue+mysql老年大学会员管理系统+PPT+论文+讲解+售后

现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本老粘大学会员管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&a…

HTML4(二)

文章目录 1 开发者文档2 基本标签2.1 排版标签2.2 语义化标签2.3 行内元素与块级元素2.4 文本标签2.5 常用标签补充 3 图片标签4 超链接标签4.1 跳转页面4.2 跳转文件4.3 跳转锚点4.4 唤起指定应用 5 列表5.1 有序列表5.2 无序列表5.3 自定义列表 6 表格6.1 基本结构6.2 表格标…

如何查看页面对应的Selenium定位参数

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

IO 5.10

在一个进程中&#xff0c;创建一个子线程。 主线程负责&#xff1a;向文件中写入数据 子线程负责&#xff1a;从文件中读取数据 要求使用线程的同步逻辑&#xff0c;保证一定在主线程向文件中写入数据成功之后&#xff0c;子线程才开始运行&#xff0c;去读取文件中的数据#incl…

bean在java中什么意思?这篇文章带你详细了解

bean在java中什么意思&#xff1f;这篇文章带你详细了解 在Java的世界里&#xff0c;你可能会经常听到“Bean”这个词。它听起来像咖啡豆&#xff0c;但实际上与咖啡无关。那么&#xff0c;Java Bean到底是什么呢&#xff1f; 简单来说&#xff0c;Bean是一种特殊的Java类&…

麒麟kylin-v10系统,虚拟机kvm的使用

kvm的使用 虚拟机新建 点击选择对应的iso文件 选择相应的系统 &#xff08;注意&#xff0c;如果这里没有相应的系统比如&#xff1a;windows&#xff0c;可以直接选择Generic default这是通用默认的意思&#xff09; 选择cpu 完成即可 等待安装完毕 网络设置-ssh连接 虚拟…

2024.5.10

数据库删除操作 //删除操作的槽 void Widget::on_delbt_clicked() {QString sql;if(ui->idedit->text()NULL){sql "drop Stu";}else{sql QString("delete from Stu where id %1").arg(ui->idedit->text());}QSqlQuery query;if(!query.exe…

看懂这4点,保证让你顺利申请小程序地理位置接口

小程序地理位置接口有什么功能&#xff1f; 通常情况下&#xff0c;我们在开发小程序时&#xff0c;可能会用到获取用户地理位置信息的功能。小程序开发者开放平台的新规定指出&#xff0c;如果没有申请开通微信小程序地理位置接口&#xff08;getLocation&#xff09;&#xf…

OSPF虚链路

原理概述 通常情况下&#xff0c;一个OSPF网络的每个非骨干区域都必须与骨干区域通过ABR路由器直接连接&#xff0c;非骨干区域之间的通信都需要通过骨干区域进行中转。但在现实中&#xff0c;可能会因为各种条件限制&#xff0c;导致非骨干区域和骨干区域无法直接连接&#x…

Mysql的关联查询以及语句

一、mysql的连接查询 1、等值连接 这里是三张表的等值连接 select rp.role_id,rp.permission_id from role_permission rp, role r, permission p where rp.role_idr.id and rp.permission_idp.id 2、内连接&#xff1a; 角色&#xff1a;系统管理员 是否拥有权限&#xf…

【JVM】垃圾回收机制(Garbage Collection)

目录 一、什么是垃圾回收&#xff1f; 二、为什么要有垃圾回收机制&#xff08;GC&#xff09;&#xff1f; 三、垃圾回收主要回收的内存区域 四、死亡对象的判断算法 a&#xff09;引用计数算法 b&#xff09;可达性分析算法 五、垃圾回收算法 a&#xff09;标记-清除…

ICode国际青少年编程竞赛- Python-3级训练场-if else语句

ICode国际青少年编程竞赛- Python-3级训练场-if else语句 1、 for i in range(9):if Flyer[i].x < Dev.x:Flyer[i].step(Dev.x - Flyer[i].x)else:Flyer[i].step(Flyer[i].x - Dev.x) Dev.step(Dev.y - Item.y)2、 for i in range(6):if Flyer[i].x < Dev.x:# 满足条…

哪里有高清视频素材软件?哪里有视频素材网站?

在这个视觉内容至关重要的时代&#xff0c;高质量的视频素材不仅能够增强信息传递的效果&#xff0c;还能显著提升观众的观看体验。接下来介绍的这些视频素材网站&#xff0c;将为您的创作提供广泛的选择&#xff0c;从本土到国际&#xff0c;满足您不同的需求和偏好。 1. 蛙学…

【Qt 学习笔记】Qt常用控件 | 多元素控件 | List Widget的说明及介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 多元素控件 | List Widget的说明及介绍 文章编号&#x…

Linux -- 日志

一 日志的重要性 在之前的编程经历中&#xff0c;如果我们的程序运行出现了问题&#xff0c;都是通过 标准输出 或 标准错误 将 错误信息 直接输出到屏幕上&#xff0c;以此来排除程序中的错误。 这在我们以往所写的程序中使用没啥问题&#xff0c;但如果出错的是一个不断在运行…

ICode国际青少年编程竞赛- Python-3级训练场-综合练习3

ICode国际青少年编程竞赛- Python-3级训练场-综合练习3 1、 for i in range(10):if i < 2 or i > 7: Flyer[i].step(1) Dev.step(Dev.y - Item[0].y)2、 for i in range(8):if i < 3 or i > 4:Spaceship.turnRight()else:Spaceship.turnLeft()Spaceship.step(i …

YUV中Y颜色模型的采样

YUV的特点 相对于表示颜色的GUI&#xff0c; YUI将亮度&#xff08;用Y表示&#xff09;与色调&#xff08;用U和V表示&#xff09;分开来表示。又因为人类视网膜上的视网膜杆细胞要多于视网膜锥细 胞&#xff0c;说得通俗一些&#xff0c;视网膜杆细胞的作用就是识别亮度&…

举办《Llama3关键技术深度解析与构建Responsible AI、算法及开发落地实战》线上高级研修讲座

举办《Llama3关键技术深度解析与构建Responsible AI、算法及开发落地实战》线上高级研修讲座

数据库的一些知识点

数据模型的组成要素中&#xff0c;描述数据库的组成对象以及对象之间的联系的是&#xff08; &#xff09;。 A 数据结构 B 数据操作 C 数据的完整性约束条件 D 数据的安全性约束条件 2.单选题 (2分) 若关系中的某一组属性的值能够唯一地标识一个元组&#xff0c;而其子集…