雪花算法介绍

文章目录

    • 概述
    • Snowflake算法结构
    • 雪花算法的优缺点
    • 解决唯一ID这个问题解决方法
    • Snowflake算法生成ID的过程
    • Java 实现示例

概述

Snowflake算法是Twitter开发的一种分布式唯一ID生成算法,用于解决在分布式系统中生成全局唯一ID的问题。该算法的核心思想是通过对64位的ID进行合理的位分配,保证在分布式环境下生成的ID具有全局唯一性和有序性。

Snowflake算法结构

在这里插入图片描述 64位ID结构:Snowflake算法生成的ID是一个64位的整数,其中各部分如下所示: 符号位(第1位):始终为0,用于保证生成的ID为正数。时间戳(41位):记录生成ID的时间戳,单位是毫秒,可以支持约69年的时间范围。机器ID(10位):标识机器的唯一ID,每台机器需要分配一个唯一的ID。序列号(12位):表示同一毫秒内生成的序列号,支持每台机器每毫秒生成4096个ID。
最高位是符号位,始终为0,不可用。
41位的时间序列,精确到毫秒级,41位的长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) 后得到的值,这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序SnowFlake类的START_STMP属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
10位的机器标识,10位的长度最多支持部署1024个节点。
12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个ID序号,12位的计数序列号支持每个节点每毫秒产生4096个ID序号。
加起来刚好64位,为一个Long型。这个算法很简洁,但依旧是一个很好的ID生成策略。其中,10位器标识符一般是5位IDC+5位machine编号,唯一确定一台机器。

雪花算法一种生成分布式全局唯一 ID 算法,生成 ID 称为SnowflakeIDs。这种算法由 Twitter 创,并用于推文 ID。一个 Snowflake ID 有 64 位元。
第 1 位:Java 中 long 最高位符号位代表正负,正数 0,负数1
一般生成 ID 都为正数,所以默认为 0。下来前 41 位时间戳,表示了自选定时期以来毫秒数。下来 10 位代表计算机 ID,防止冲突。
其余 12 位代表每台机器上生成 ID 序列号,这允许在同一毫秒内创多个Snowflake ID。
雪花算法一般用来实现全局唯一的业务主键,解决分库分表之后主键id的唯一性问题。
而雪花算法就是一个比较符合这类特征的全局唯一算法,在美团的Leaf组件中也有用到。
它是由一个64位的long类型数字组成,分为四个部分。
第一部分,用1个bit表示符号位,一般情况下是0
第二部分,用41个bit来表示时间戳,使用系统时间的毫秒数
第三部分,用10个bit来记录工作机器id,这样就可以保证在多个服务器上生成的id的唯一性。
如果存在跨机房部署,我们还可以把它分成两个5bit,前面5个bit可以表示机房id,后面5个bit可以
表示机器id。
第四个部分,用12个bit表示序列号,表示一个递增序列,用来记录同毫秒内产生的不同id
雪花算法,就是根据这四个部分的规则,生成对应的bit位数据,然后组装在一起形成一个全局唯一id。
雪花算法英文翻译为 Snow Flake 算法,它是由Twitter开源的分布式 ID生成算法。主要应用于分库分表场
景中的全局ID作为业务主键,或者生成全局唯一的订单号。
那为什么要叫雪花算法呢?据相关研究表示,一般的雪花大约由10的19次方个水分子组成。在雪花形成过
程中,会形成不同的结构分支,所以说大自然中不存在两片完全一样的雪花,每一片雪花都拥有自己独特的形
状。雪花算法的意思是表示生成的ID如雪花一般独一无二。
实现原理
雪花算法那是一个由64个Bit(比特)位组成的long类型的数字。如图所示,它分为四个部分。
第一部分,用1个bit(比特)位来表示1个符号位,因为ID一般不会是负数,所以一般情况下就是0。
第二部分,用41个bit(比特)位来表示系统时间戳,这个时间戳就是系统时间记录的毫秒数。41个bit可以表示的
最大数字为2的41次方减1毫秒,换算成时间为69年。
第三部分,用10个bit(比特)位来技术工作机器的ID,用来保证多个服务器上生成ID的唯一性。如果存在跨机
房部署的情况,还可以把这10个比特位拆分为两组,每组5个bit(比特)位。前面的5个bit(比特)表示机房ID,
后面5个bit(比特)表示机器ID。10个比特位最大值是2的10次方,也就是最多1024台机器。
第四部分,用12个比特位来表示递增序列,用来记录同一毫秒内产生不同ID的能力。它的最大值为2的12次方减1,也就是4096。
雪花算法就是根据这四个部分的组成规则,生成对应Bit位的数据,然后组装到一起生成一个全局唯一ID。

雪花算法的优缺点

雪花算法主要有以下优点:
1)分布式系统内不会产生ID碰撞,效率高。
2)不需要依赖数据库等第三方系统,稳定性更高,可以根据自身业务分配bit位,非常灵活。
3)生成ID的性能也非常高,每秒能生成26万个自增可排序的ID。
优点:实现简单、高效,生成ID速度快,ID呈递增趋势,适合在分布式系统中大规模使用。
缺点:依赖系统时钟,如果系统时间回拨可能会导致ID重复;机器ID需要提前分配,限制了扩展性。
当然,雪花算法那也有缺点,因为它依赖机器时钟,如果机器时钟回拨,可能会导致ID重复。如果再分布式环境下,每台机器上的时钟不可能完全同步,有时候会出现不是全局递增的情况。当然,大部分情况下可以忽略这一缺点。

解决唯一ID这个问题解决方法

比如UUID、系统时间戳、Redis原子递增、数据库全局表
自增ID等等。但是在实际应用中,我们需要的ID除了唯一性以外,还需要满足以下特征:
1)、单调递增:保证下一个ID号一定大于上一个。
2)、保证安全:ID号需要无规则性,不能让别人根据ID号猜出我们的信息和业务数据量,增加恶意用户扒取数据的难度。
3)、含时间戳:需要记录系统时间戳
4)、高可用:发布一个获取分布式ID的请求,服务器至少要保证99.999%的情况下给创建一个全局唯一的分布式ID。
5)、低延迟:发布一个获取分布式ID的请求,要快,急速。
6)、高QPS:假如并发一口气10万个创建分布式ID请求同时杀过来,服务器要顶得住并且成功创建10万个分布式ID。
雪花算法就是一个比较符合这类特征的全局唯一算法。在很多大厂的全局ID组件中,都有用到,比如百度的UidGenerator、美团的Leaf算法等等。

Snowflake算法生成ID的过程

生成ID的过程:
当需要生成一个新的ID时,Snowflake算法根据当前时间戳、机器ID和序列号来生成一个唯一的ID。
首先获取当前时间戳,然后将时间戳左移22位,给机器ID留出10位的空间。
将机器ID左移12位,空出序列号的位数。
序列号部分初始化为0,如果同一毫秒内生成多个ID,序列号递增,超过4096则等待下一毫秒再生成。
ID的唯一性:
Snowflake算法通过合理分配时间戳、机器ID和序列号来保证生成的ID在分布式环境中的唯一性。不同机器的ID不同,同一毫秒内生成的ID序列号也不同,这样可以避免ID重复的情况发生。
总的来说,Snowflake算法是一种简单有效的分布式唯一ID生成算法,适用于各种分布式系统场景,但在使用时需要注意时钟同步和机器ID的分配等问题。

Java 实现示例

以下是一个简单的 Java 实现示例,用于生成 Snowflake 算法的唯一 ID:

public class SnowflakeIdGenerator {

    private final long workerId;
    private final long epoch = 1609459200000L; // 起始时间戳,这里以2021-01-01 00:00:00为起始时间
    private long sequence = 0L;
    private final long workerIdBits = 5L;
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private final long timestampLeftShift = 22L;
    private final long workerIdShift = 12L;
    private final long sequenceMask = -1L ^ (-1L << 12L);
    private long lastTimestamp = -1L;

    public SnowflakeIdGenerator(long workerId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException("Worker ID can't be greater than " + maxWorkerId + " or less than 0");
        }
        this.workerId = workerId;
    }

    public synchronized long nextId() {
        long timestamp = System.currentTimeMillis();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds");
        }
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        return ((timestamp - epoch) << timestampLeftShift) | (workerId << workerIdShift) | sequence;
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

    public static void main(String[] args) {
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1); // 传入当前机器的ID
        System.out.println(idGenerator.nextId());
    }
}

在上面的示例中,我们创建了一个名为 SnowflakeIdGenerator 的类,通过调用 nextId() 方法来生成唯一的 ID。在 main 方法中,我们实例化了 SnowflakeIdGenerator 并调用 nextId() 方法来生成一个 ID。请注意,这里的 workerId 需要根据实际情况设置为当前机器的唯一标识符。
总之,这段代码演示了如何使用 Java 实现基本的 Snowflake 算法来生成唯一的 ID。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java程序设计】【C00385】基于(JavaWeb)Springboot的员工信息管理系统(有论文)

基于&#xff08;JavaWeb&#xff09;Springboot的员工信息管理系统 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c…

Learn OpenGL 32 PBR光照

光照 在本章节中&#xff0c;我们把重点放在将之前讨论的理论转化为实际的渲染器&#xff0c;这个渲染器将使用直接的&#xff08;或解析的&#xff09;光源&#xff1a;比如点光源&#xff0c;定向灯或聚光灯。 我们先来看看上一个章提到的反射方程的最终版&#xff1a; 我们…

UI自动化测试用例管理平台搭建

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 用到的工具&#xff1a;python3 django2 mysql RabbitMQ celery selenium python3和selen…

Linux系统编程--信号

1、信号&#xff08;一&#xff09; 1.1、什么是中断 1.2、中断分类 1.3、信号 1.4、信号与中断 1.5、信号名称 1.6、进程对信号的三种响应 1.7、signal函数&#xff1a;注册信号 signal(SIGINT, handler);返回值是SIGINT所对应的处理程序 再调用一下signal(SIGINT, handler2…

QT数据类型和容器用法

Qt库提供了基于通用模板的容器类, 这些类可用于存储指定类型的数据项&#xff0c;Qt中这些容器类的设计比STL容器更轻&#xff0c;更安全且更易于使用。容器类也都是隐式共的&#xff0c;它们是可重入的&#xff0c;并且已针对速度/低内存消耗和最小的内联代码扩展进行了优化&a…

(二)windows配置JDK环境

1、安装包下载地址,官网:Java Archive | Oracle 长期稳定支持版本8、11、17、21 选择一个需要下载的连接点进去: 在下载列表中根据操作系统选择不同的下载包: 注意:部分版本下载需要先登录后才可以下载。

Vit Transformer

一 VitTransformer 介绍 vit : An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 论文是基于Attention Is All You Need&#xff0c;由于图像数据和词数据数据格式不一样&#xff0c;经典的transformer不能处理图像数据&#xff0c;在视觉领域的应…

C++电子宠物商店

一、功能描述 店内有不同类型的电子宠物 1.每种电子宠物能通过显示出来的文本提出需要或表示情绪如&#xff1a;饿、渴、饱涨、困、不舒服、高兴、生气、伤心、绝望、无聊等。 2.店员用户通过键盘操作“饲养”电子宠物&#xff0c;给它实施喂饭、喂水、带它上厕所、陪它玩耍、…

3.27作业

1、完成下面类 #include <iostream> #include <cstring> using namespace std;class myString { private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度 public://无参构造myString():size(10){str new char[size]; …

凯撒加密.

题目描述 给定一个单词&#xff0c;请使用凯撒密码将这个单词加密 凯撒密码是一种替换加密的技术&#xff0c;单词中的所有字母都在字母表上向后偏移3位后被替换成密文。即a变为 d&#xff0c;变为e.&#xff0c;w 变为z&#xff0c;2 变为a&#xff0c;y变为 6&#xff0c;z变…

javaWeb项目-大学生体质测试管理系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、JSP技术 JSP(Jav…

python笔记进阶--面向对象(2)

目录 1.类和对象&#xff08;实例&#xff09; 1.1对象&#xff08;实例&#xff09; 1.1.1使用对象组织数据 1.1.2类中增加属性 1.2成员方法&#xff08;类&#xff09; 1.2.1类的定义和使用语法 1.2.2成员方法的使用 1.2.3self关键字的作用 1.3类和对象 2&#xff…

Mysql各种日志管理

文章目录 事务日志事务日志的记录过程事务日志类型事务日志的相关变量 错误日志二进制日志功能作用文件的构成日志格式查看日志删除日志 通用日志慢查询日志 Mysql日志记录着数据库在运行过程中的各种操作&#xff0c;帮助管理员定位查找问题。 事务日志 事务日志(Transaction…

方案分享 | 嵌入式指纹方案

随着智能设备的持续发展&#xff0c;指纹识别技术成为了现在智能终端市场和移动支付市场中占有率最高的生物识别技术。凭借高识别率、短耗时等优势&#xff0c;被广泛地运用在智能门锁、智能手机、智能家居等设备上。 上海航芯在2015年进入指纹识别应用领域&#xff0c;自研高性…

MySQL的安装(Linux版)

1.所需要的文件 MySQL.zip 2. 卸载自带的Mysql-libs # 查看是否存在 rpm -qa | grep mariadb# 如果存在则执行命令进行卸载 rpm -e --nodeps mariadb-libs3.在/opt目录下创建MySQL目录并上传所需要的安装包 cd /optmkdir MySQL4.按照编号顺序安装&#xff08;压缩包在解压完…

vs2010打包QT程序

一、环境 win10 、 VS2010 、 qt5.7.1 将代码在release模式下运行 运行完后会在相应的文件夹下生成exe文件&#xff0c;也会将部分dll文件拷贝到release文件夹中 二、生成可执行文件 2.1 选择“文件”->“新建”->”项目“ 2.2 在打开的对框中选择”其他类型项目…

视频素材网有哪些?7个优质无水印素材库推荐

当今社会&#xff0c;视频内容已成为最吸引眼球的媒介之一&#xff0c;无论是社交媒体的短视频还是专业制作的影片&#xff0c;都离不开高质量的视频素材。为了帮助你在茫茫网海中找到宝藏&#xff0c;下面我精选了一系列视频素材网站&#xff0c;不仅提供丰富多样的视频资源&a…

(1) 易经与命运_学习笔记

个人笔记&#xff0c;斟酌阅读 占卦的原理 三个铜板&#xff0c;正面是3&#xff0c;反面2&#xff0c;三个一起转&#xff0c;得出6,7,8,9 数字象6老阴7少阳8少阴9老阳 生数和成数 生数和成数应该说出自《河图》。其中一二三四五为生数&#xff0c;六七八九十为成数。 生…

Typst入门简明教程

文章目录 写在前面对比阅读安装Typst的安装系统路径设置VSCode的设置 用Typst写作节指令图指令表指令公式指令参考文献指令引用指令节的标签图、表、公式的标签参考文献的标签 Typst编译 Typst的<label>写法建议写在最后&#xff1a;Typst、LaTex和Word的比较 写在前面 …

面试经典150题【111-120】

文章目录 面试经典150题【111-120】67.二进制求和190.颠倒二进制位191.位1的个数136.只出现一次的数字137.只出现一次的数字II201.数字范围按位与5.最长回文子串97.交错字符串72.编辑距离221.最大正方形 面试经典150题【111-120】 六道位运算&#xff0c;四道二维dp 67.二进制…