聊聊雪花算法?

article/2025/9/19 19:24:24

随便聊聊

哈喽,大家好,最近换了份工作,虽然后端技术栈是老了点,但是呢,这边的前端技术确是现在市面上最新的那一套技术:Vue3+Vite+TSX+Pina+Element-Plus+NativeUI。我本人主要是学后端的,确被拉去做前端。唉(人生无常,大肠包小肠!)

但是呢,最近经常听到同事们一直在聊雪花算法,下面来,我们来聊聊雪花算法,是的

分布式ID

聊之前先说一下什么是分布式ID,抛砖引玉

假设现在有一个订单系统被部署在了A、B两个节点上,那么如何在这两个节点上各自生成订单ID,且ID值不能重复呢?

即在分布式系统中,如何在各个不同的服务器上产生唯一的ID值?

通常有以下三种方案:

  • 利用数据库的自增特性,不同节点直接使用相同数据库的自增ID;
  • 利用UUID算法产生ID值;
  • 使用雪花算法产生ID值

虽然Java提供了对UUID的支持,使用UUID.randomUUID()即可,但是由于UUID是一串随机的36位字符串,由32个数字和字母混合的字符串和4个“-”组成,长度过长且业务可读性差,无法有序递增,所以一般不用,更多使用的是雪花算法

由来

为什么叫雪花算法?

雪花算法的由来有两种说法:

  • 第一种,Twitter使用scala语言开源了一种分布式id生成算法—SnowFlake算法,被翻译成了雪花算法;
  • 第二种,因为自然界中并不存在两片完全一样的雪花的,每一片雪花都拥有自己漂亮独特的形状、独一无二。雪花算法也表示生成的ID如雪花般独一无二。

组成

雪花算法生成的ID到底长啥样?

雪花算法生成的ID是一个64bit的long型的数字且按时间趋势递增。大致由首位无效符、时间戳差值、机器编码,序列号四部分组成。
在这里插入图片描述
如图:

  • 首位无效符:第一个bit作为符号位,因为我们生成的都是正数,所以第一个bit统一都是0;
  • 时间戳:占用41bit,精确到毫秒。41位最好可以表示2^41-1毫秒,转换成单位年为69年;
  • 机器编码:占用10bit,其中高位5bit是数据中心ID,低位5bit是工作节点ID,最多可以容纳1024个节点;
  • 序列号:占用12bit,每个节点每毫秒0开始不断累加,最多可以累加到4095,一共可以产生4096个ID

代码

/*** 雪花算法* @author Fang Ruichuan* @date 2022-11-28 21:24*/
public class SnowFlake {private long workerId;private long dataCenterId;// 每毫秒生产的序列号之从0开始递增private long sequence = 0L;// 1288834974657L是1970-01-01 00:00:00到2010年11月04日01:42:54所经过的毫秒数;// 因为现在二十一世纪的某一时刻减去1288834974657L的值,正好在2^41内。// 因此1288834974657L实际上就是为了让时间戳正好在2^41内而凑出来的。// 简言之,1288834974657L(即1970-01-01 00:00:00),就是在计算时间戳时用到的“起始时间”。private long twePoch = 1288834974657L;private long workerIdBits = 5L;private long datacenterIdBits = 5L;private long maxWorkerId = -1L ^ (-1L << workerIdBits);private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);private long sequenceBits = 12L;private long workerIdShift = sequenceBits;private long datacenterIdShift = sequenceBits + workerIdBits;private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;private long sequenceMask = -1L ^ (-1L << sequenceBits);private long lastTimestamp = -1L;public SnowFlake(long datacenterId, long workerId) {if ((datacenterId > maxDatacenterId || datacenterId < 0)|| (workerId > maxWorkerId || workerId < 0)) {throw new IllegalArgumentException("datacenterId/workerId值非法");}this.dataCenterId = datacenterId;this.workerId = workerId;}// 通过SnowFlake生成id的核心算法public synchronized long nextId() {long timestamp = Clock.systemUTC().millis();if (timestamp < lastTimestamp) {throw new RuntimeException("时间戳值非法");}// 如果此次生成id的时间戳,与上次的时间戳相同,就通过机器码和序列号区// 分id值(机器码已通过构造方法传入)if (lastTimestamp == timestamp) {/*下一条语句的作用是:通过位运算保证sequence不会超出序列号所能容纳的最大值。例如,本程序产生的12位sequence值依次是:1、2、3、4、...、4094、4095(4095是2的12次方的最大值,也是本sequence的最大值)那么此时如果再增加一个sequence值(即sequence + 1),下条语句就会使sequence恢复到0。即如果sequence==0,就表示sequence已满。*/sequence = (sequence + 1) & sequenceMask;// 如果sequencce已满,就无法再通过sequence区分id值:因此需要切换到if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {// 如果此次生成id的时间戳,与上次的时间戳不同,就已经可以根据时间戳区分id值sequence = 0L;}// 更新最近一次次生成id的时间戳lastTimestamp = timestamp;/**** 假设此刻的值是(二进制表示):*                 41位时间戳的值是:00101011110101011101011101010101111101011*                 5位datacenterId(机器码的前5位)的值是:01101*                 5位workerId(机器码的后5位)的值是:11001*                 sequence的值是:01001*             那么最终生成的id值,就需要:*                 1.将41位时间戳左移动22位(即移动到snowflake值中时间戳应该出现的位置);*                 2.将5位datacenterId向左移动17位,并将5位workerId向左移动12位*                 (即移动到snowflake值中机器码应该出现的位置);*                 3.sequence本来就在最低位,因此不需要移动。*             以下<<和|运算,实际就是将时间戳、机器码和序列号移动到snowflake中相应的位置。* @return long*/return ((timestamp - twePoch) << timestampLeftShift)| (dataCenterId << datacenterIdShift) | (workerId << workerIdShift)| sequence;}private long tilNextMillis(long lastTimestamp) {long timestamp = Clock.systemUTC().millis();// 如果当时时刻的时间戳 <= 上一次生成id的时间戳,就重新生成当前时间;// 即确保当前时刻的时间戳,与上一次的时间戳不会重复while (timestamp <= lastTimestamp) {timestamp = Clock.systemUTC().millis();}return timestamp;}// 测试1秒能够生成的id个数public static void generateIdsInOneSecond() {SnowFlake idWorker = new SnowFlake(1, 1);long start = Clock.systemUTC().millis();int i = 0;for (; Clock.systemUTC().millis() - start < 1000; i++) {idWorker.nextId();}long end = Clock.systemUTC().millis();System.out.println("耗时:" + (end - start));System.out.println("生成id个数:" + i);}public static void main(String[] args) {generateIdsInOneSecond();}
}

测试结果:

耗时:1000
生成id个数:4082481

http://chatgpt.dhexx.cn/article/ULgSUhKC.shtml

相关文章

雪花算法生成实例

雪花算法生成实例 一、集群高并发情况下如何保证分布式唯一全局id生成&#xff1f;1.1 为什么需要分布式全局唯一ID以及分布式ID的业务需求1.2 ID生成规则部分硬性要求1.3 ID号生成系统的可用性要求 二、一般通用方案2.1 UUID2.2 数据库自增主键2.3 基于Redis生成全局id策略2.4…

算法 —— 雪花算法

文章目录 算法 —— 雪花算法简介实现原理结构图 算法 —— 雪花算法 简介 雪花算法是由 Twitter 公布的分布式主键生成算法&#xff0c;它能够保证不同进程主键的不重复性&#xff0c;以及相同进程主键的有序性。 实现原理 在同一个进程中&#xff0c;它首先是通过时间位保…

java雪花算法实现

基于雪花算法&#xff08;Snowflake&#xff09;模式雪花算法&#xff08;Snowflake&#xff09;是twitter公司内部分布式项目采用的ID生成算法&#xff0c;开源后广受国内大厂的好评&#xff0c;在该算法影响下各大公司相继开发出各具特色的分布式生成器。 Snowflake生成的是L…

雪花算法的实现原理

一位工作4年的小伙伴&#xff0c;去某东面试时被问到这样一道题&#xff0c;说请你简述一下雪花算法的实现原理。屏幕前的小伙伴&#xff0c;如果你遇到这个问题&#xff0c;你会怎么回答&#xff1f; 今天&#xff0c;我给大家分享一下我的理解。 1、什么是雪花算法 雪花算…

Python 实现雪花算法

Python 实现雪花算法 雪花算法&#xff1a;雪花算法是一种分布式全局唯一ID&#xff0c;一般不需要过多的深入了解&#xff0c;一般个人项目用不到分布式之类的大型架构&#xff0c;另一方面&#xff0c;则是因为&#xff0c;就算用到市面上很多 ID 生成器帮我们完成了这项工作…

雪花算法简介以及代码实现

文章目录 雪花算法分布式ID分布式ID需要满足的要求全局唯一:高性能:高可用:方便易用:安全:有序递增:要求具体的业务含义:独立部署: 组成代码实现Java代码实现Go语言实现 雪花算法 简介: 雪花算法是Twitter开源的分布式ID生成算法 Github仓库地址 雪花算法主要用于分布式系统中…

雪花算法(id生成算法)

SnowFlake 雪花算法 SnowFlake 中文意思为雪花&#xff0c;故称为雪花算法。最早是 Twitter 公司在其内部用于分布式环境下生成唯一 ID。在2014年开源 scala 语言版本。 实现原理 雪花算法原理就是生成一个的64位比特位的 long 类型的唯一 id。 最高1位固定值0&#xff0c…

什么是雪花算法?啥原理?

1、SnowFlake核心思想 SnowFlake 算法&#xff0c;是 Twitter 开源的分布式 ID 生成算法。 其核心思想就是&#xff1a;使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛&#xff0c;且 ID 引入了时间戳&#xff0c;基本上保持自增的&#xf…

雪花算法-java

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;计算机基础专栏 &#x1f4e7;如果文章知识点有错误的地方&#…

数据库中雪花算法是什么?

一、为何要用雪花算法 1、问题产生的背景 现如今越来越多的公司都在用分布式、微服务&#xff0c;那么对应的就会针对不同的服务进行数据库拆分&#xff0c;然后当数据量上来的时候也会进行分表&#xff0c;那么随之而来的就是分表以后id的问题。 例如之前单体项目中一个表中…

snowflake算法(雪花算法)

snowflake算法(雪花算法) 1.snowflake算法介绍 Snowflake算法产生是为了满足Twitter每秒上万条消息的请求&#xff0c;每条消息都必须分配一条唯一的id&#xff0c;这些id还需要一些大致的顺序&#xff08;方便客户端排序&#xff09;&#xff0c;并且在分布式系统中不同机器…

分布式ID生成算法——雪花算法

一、分布式ID ID可以唯一标识一条记录。 对于单体架构&#xff0c;我们可以使用自增ID来保证ID的唯一性。但是&#xff0c;在分布式系统中&#xff0c;简单的使用自增ID就会导致ID冲突。这也就引出了分布式ID问题。分布式ID也要求满足分布式系统的高性能、高可用、高并发的特点…

【SnowFlake】雪花算法(Java版本)

SnowFlake雪花算法&#xff08;Java版本&#xff09; 一、SnowFlake算法二、代码实现三、应用场景四、优缺点五、分布式生成ID方式 一、SnowFlake算法 雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法 Snowflake生成的是Long类型的ID&#xff0c;一个Long类型…

雪花算法以及具体实现

一、为何要用雪花算法 1、问题产生的背景 现如今越来越多的公司都在用分布式、微服务&#xff0c;那么对应的就会针对不同的服务进行数据库拆分&#xff0c;然后当数据量上来的时候也会进行分表&#xff0c;那么随之而来的就是分表以后id的问题。 例如之前单体项目中一个表中的…

什么是雪花算法,详解雪花算法原理

雪花算法(SnowFlake) 雪花算法是Twitter开源的分布式ID生成算法. 主要是由64bit的long型生成的全局ID,引入了时间戳和ID保持自增的属性. 64bit分为四个部分: 第一个部分是1bit, 这不 使用,没有意义; 第二个部分是41bit, 组成时间戳; 第三个部分是10bit, 工作机器ID,里面分为…

雪花算法原理及实现

背景 分布式高并发的环境下&#xff0c;最常见的就是每年双十一的十二点&#xff0c;大量用户同时抢购同一商品&#xff0c;毫秒级的时间下可能生成数万个订单&#xff0c;此时确保生成订单ID的唯一性变得至关重要。此外&#xff0c;在秒杀环境下&#xff0c;不仅要保障ID唯一…

雪花算法的原理和实现Java

SnowFlake 算法&#xff0c;是 Twitter 开源的分布式 id 生成算法。其核心思想就是&#xff1a;使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛&#xff0c;且ID 引入了时间戳&#xff0c;基本上保持自增的&#xff0c;后面的代码中有详细的注…

雪花算法简介

文章目录 1、简介2、雪花算法3、算法实现4、算法优缺点5、补充 1、简介 在生成随机主键的时候&#xff0c;我第一个想到的就是UUID&#xff0c;但是UUID在MySQL中作为主键生成时&#xff0c;就会出现一个问题&#xff0c;UUID生成的是乱序的。这时候&#xff0c;学习MP的过程中…

雪花算法

文章目录 1、雪花算法的起源2、雪花算法原理3、雪花算法java实现4、一些细节讨论4.1调整比特位分布4.2workerid一般如何生成 1、雪花算法的起源 snowflake中文的意思是 雪花&#xff0c;雪片&#xff0c;所以翻译成雪花算法。它最早是twitter内部使用的分布式环境下的唯一ID生…

SnowFlake 雪花算法详解与实现

我是陈皮&#xff0c;一个在互联网 Coding 的 ITer&#xff0c;个人微信公众号「陈皮的JavaLib」关注第一时间阅读最新文章。 文章目录 背景SnowFlake 雪花算法算法实现算法验证算法优缺点注意事项 背景 现在的服务基本是分布式&#xff0c;微服务形式的&#xff0c;而且大数据…