当前位置: 首页 > news >正文

雪花算法(Snowflake Algorithm)

雪花算法(Snowflake Algorithm)是一种分布式唯一ID生成算法,主要用于生成全球唯一的ID,广泛应用于分布式系统中,例如在数据库中作为主键。这个算法最初由Twitter提出,并且被广泛使用在很多大规模系统中。有以下特性:

唯一性: 确保生成的每一个ID都是全球唯一的,避免冲突。

时间有序性: 根据生成ID的时间戳,使得ID按时间顺序排列,方便进行时间排序和处理。

高效性: 在高并发环境下能够快速生成ID,通常在每毫秒内能够生成多个ID。

雪花算法的核心思想是将ID分解成几个部分,以确保生成的ID具有唯一性,同时又能保持一定的顺序性。它的ID结构一般包括以下几个部分:

时间戳(Timestamp): 用于表示当前时间的毫秒数。通常,时间戳占用最前面的一部分位数,这样可以保证ID在时间上有序。

数据中心ID(Data Center ID): 用于标识不同的数据中心,确保在不同的数据中心生成的ID不会冲突。

工作机器ID(Worker ID): 用于标识同一数据中心下的不同工作机器,确保同一数据中心内的不同机器生成的ID也不会冲突。

序列号(Sequence Number): 用于在同一毫秒内生成多个ID,以保证同一时间戳下生成的ID仍然唯一。

雪花算法通常生成的ID长度是64位,具体结构可能有所不同,但一个常见的结构是:

1位符号位(通常固定为0)

41位时间戳(表示毫秒数,一般支持约69年的时间范围)

10位数据中心ID和工作机器ID(分为5位数据中心ID和5位工作机器ID,支持最多1024个数据中心,每个数据中心支持最多1024台机器)

12位序列号(支持每毫秒生成4096个不同的ID)

这种设计可以保证生成的ID是全局唯一的,同时还能保持一定的顺序性,适用于高并发的分布式系统。

工作原理

生成ID时,算法会获取当前时间戳。

结合数据中心ID、工作机器ID以及序列号生成唯一ID。

如果在同一毫秒内生成多个ID,算法会增加序列号以确保唯一性。

在时间戳变化时,算法会重置序列号,并更新ID的时间戳部分。

优点有:

全局唯一性:‌能够在分布式系统中确保生成的ID全局唯一。‌

趋势递增性:‌生成的ID基本呈趋势递增,‌有利于数据库性能优化。‌

灵活性:‌可以根据业务特性灵活分配bit位。‌

高性能:‌不依赖数据库等第三方系统,‌以服务方式部署,‌生成ID的性能高。‌

缺陷有:‌

时钟回退问题:雪花算法依赖于系统时间戳来生成唯一 ID。如果系统时间被设置回过去,可能会导致生成重复的 ID 或者抛出异常。这是使用雪花算法时需要特别注意的问题,因为时钟回退会直接影响到 ID 的唯一性和生成稳定性。

时间戳依赖:雪花算法的 ID 生成是基于系统时间戳的。如果系统时间出现问题(如时钟漂移或系统时间错误),则会影响 ID 的生成。这使得系统时间的准确性和稳定性变得至关重要。

数据中心 ID 和工作机器 ID 的管理:需要合理分配和管理数据中心 ID 和工作机器 ID,以避免冲突。在大规模分布式系统中,如何分配和协调这些 ID 是一个挑战,错误的配置可能导致 ID 冲突或生成不一致。

高并发处理复杂性:在高并发场景下,雪花算法通过序列号来处理生成的 ID,但在极高负载情况下,仍然需要精细管理性能和同步问题。高并发可能导致性能瓶颈或增加实现的复杂性。

代码实现

public class SnowflakeIdGenerator {// 起始时间戳 (2020-01-01 00:00:00)private static final long START_TIMESTAMP = 1577836800000L;// 工作机器 ID 位数private static final long WORKER_ID_BITS = 5L;// 数据中心 ID 位数private static final long DATA_CENTER_ID_BITS = 5L;// 序列号位数private static final long SEQUENCE_BITS = 12L;// 工作机器 ID 最大值private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);// 数据中心 ID 最大值private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);// 序列号最大值private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);// 工作机器 ID 和数据中心 IDprivate final long workerId;private final long dataCenterId;// 序列号和上次时间戳private long sequence = 0L;private long lastTimestamp = -1L;/*** 构造函数,初始化工作机器 ID 和数据中心 ID。* * @param workerId 工作机器 ID* @param dataCenterId 数据中心 ID* @throws IllegalArgumentException 如果 workerId 或 dataCenterId 超出范围*/public SnowflakeIdGenerator(long workerId, long dataCenterId) {if (workerId > MAX_WORKER_ID || workerId < 0) {throw new IllegalArgumentException("Worker ID out of range");}if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {throw new IllegalArgumentException("Data Center ID out of range");}this.workerId = workerId;this.dataCenterId = dataCenterId;}/*** 生成下一个唯一的 ID。* * @return 生成的 ID*/public synchronized long nextId() {long timestamp = currentTimestamp();// 检查时钟是否回退if (timestamp < lastTimestamp) {throw new RuntimeException("Clock moved backwards. Refusing to generate id");}// 当前时间戳与上次时间戳相同,处理序列号溢出if (timestamp == lastTimestamp) {sequence = (sequence + 1) & SEQUENCE_MASK;if (sequence == 0) {timestamp = waitNextMillis(lastTimestamp);}} else {// 当前时间戳不同,重置序列号sequence = 0L;}lastTimestamp = timestamp;// 生成唯一 IDreturn ((timestamp - START_TIMESTAMP) << (WORKER_ID_BITS + DATA_CENTER_ID_BITS + SEQUENCE_BITS)) |(dataCenterId << (WORKER_ID_BITS + SEQUENCE_BITS)) |(workerId << SEQUENCE_BITS) |sequence;}/*** 等待直到下一个毫秒。* * @param lastTimestamp 上次生成 ID 的时间戳* @return 当前时间戳*/private long waitNextMillis(long lastTimestamp) {long timestamp = currentTimestamp();while (timestamp <= lastTimestamp) {timestamp = currentTimestamp();}return timestamp;}/*** 获取当前时间戳。* * @return 当前时间戳(毫秒)*/private long currentTimestamp() {return System.currentTimeMillis();}/*** 测试生成 ID。* * @param args 命令行参数*/public static void main(String[] args) {SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);for (int i = 0; i < 10; i++) {System.out.println(idGenerator.nextId());}}
}

相关文章:

雪花算法(Snowflake Algorithm)

雪花算法&#xff08;Snowflake Algorithm&#xff09;是一种分布式唯一ID生成算法&#xff0c;主要用于生成全球唯一的ID&#xff0c;广泛应用于分布式系统中&#xff0c;例如在数据库中作为主键。这个算法最初由Twitter提出&#xff0c;并且被广泛使用在很多大规模系统中。有…...

〖任务1〗ROS2 jazzy Linux Mint 22 安装教程

前言&#xff1a; 本教程在Linux系统上使用。 目录 一、linux安装二、linux VPN安装三、linux anaconda安装&#xff08;可选&#xff09;四、linux ROS2 安装五、rosdep init/update 解决方法六、安装GUI 一、linux安装 移动硬盘安装linux&#xff1a;[LinuxToGo教程]把ubunt…...

图像增强:使用周围像素填充掩码区域

制作图像需要填充的掩码区域,对需要填充的位置的mask赋值非0,不需要填充赋值为0使用cv2.inpaint对图像掩码mask中非0元素位置的图像像素进行修复。从而实现使用周围像素填充掩码区域cv2.inpaint 是 OpenCV 库中的一个函数,用于图像修复(inpainting),即填充图像中的损坏区…...

给虚拟机Ubuntu扩展硬盘且不丢数据

1.Ubuntu关机状态下先扩展&#xff0c;如扩展20GB 2.进入ubuntu&#xff0c;切换root登录&#xff0c;必须是root全选&#xff0c;否则启动不了分区工具gparted 将新的20GB创建好后&#xff0c;选择ext4,primary&#xff1b; 3.永久挂载 我的主目录在/并挂载到/dev/sda1 从图…...

Oracle(41)如何使用PL/SQL批量处理数据?

在PL/SQL中&#xff0c;批量处理数据是一种高效的方法&#xff0c;可以在数据库中处理大量数据&#xff0c;而无需逐行操作。批量处理数据的关键技术包括&#xff1a; PL/SQL表&#xff08;索引表&#xff09;&#xff1a;在内存中存储数据以进行批量操作。FORALL语句&#xf…...

JavaEE 第2节 线程安全知识铺垫1

目录 一、通过jconsole.exe查看线程状态的方法 二、Thread类的几种常见属性 三、线程状态 一、通过jconsole.exe查看线程状态的方法 通过jconsole查看线程状态非常实用的方式 只要你安装了jdk&#xff0c;大致按照这个目录就可以找到这个可执行程序&#xff1a; 然后双击这…...

LeetCode Hot100 零钱兑换

给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。 你可以认为每种硬币的数量是无限的。 示…...

微信小程序接口实现语音转文字

一、效果展示 我们有一个按钮&#xff0c;点击“开始录音”按钮&#xff0c;此时按钮变成“停止录音”并开始计时&#xff0c;点击停止录音后&#xff0c;界面上即可展示返回的文字 二、代码实现 完整代码实现见github 1.小程序端代码 // index.js const recorderManager…...

[Spark Streaming] 读取 Kafka 消息, 插入到 MySQL

以下是一个简单的使用 Spark Streaming 读取 Kafka 消息、统计数据后插入到 MySQL 中的 Scala 代码示例&#xff1a; import org.apache.spark.SparkConf import org.apache.spark.streaming.{Seconds, StreamingContext} import org.apache.spark.streaming.kafka.KafkaUtils…...

精选3款国内wordpress 主题,建站首选

WordPress作为一款功能强大且易于使用的建站平台&#xff0c;已经成为了许多企业和个人搭建网站的首选。为了帮助大家更好地选择适合自己的WordPress主题&#xff0c;小编将为大家推荐三款国内优秀的WordPress主题&#xff1a;子比主题、OneNav主题和RiTheme主题。 1.子比主题…...

JavaScript之 Uint8Array 类型数组(solana pda场景中的大小端)

文章目录 JavaScript之 Uint8Array 类型数组numberToUint8Array 数字转换为Uint8Array为什么要把数字转换为Uint8Array数字转换为Uint8Array的大小端问题solana pda场景中的大小端JavaScript之 Uint8Array 类型数组 Uint8Array 数组类型表示一个8位无符号整型数组,创建时内容…...

《Windows API每日一练》24.1 WinSock简介

本节将逐一介绍WinSock的主要特性和组件&#xff0c;套接字、WinSock动态库的使用。 本节必须掌握的知识点&#xff1a; Windows Socket接口简介 Windows Socket接口的使用 第178练&#xff1a;网络时间校验 24.1.1 Windows Socket接口简介 ■以下是WinSock的主要特性和组件…...

openwrt编译Dockerfile

一、Dockerfile FROM ubuntu:20.04ENV TZAsia/ShanghaiRUN apt-get update && \apt-get install -y --no-install-recommends tzdata && \ln -fs /usr/share/zoneinfo/$TZ /etc/localtime && \dpkg-reconfigure --frontend noninteractive tzdata &am…...

【C语言】分支与循环(循环篇)——结尾猜数字游戏实现

前言 C语言是一种结构化的计算机语言&#xff0c;这里指的通常是顺序结构、选择结构、循环结构&#xff0c;掌握这三种结构之后我们就可以解决大多数问题。 分支结构可以使用if、switch来实现&#xff0c;而循环可以使用for、while、do while来实现。 1. while循环 C语言中…...

【数据结构】链表篇

文章目录 1.链表的概念以及结构2.链表的分类2.1 单向或者双向2.2 带头或者不带头2.3 循环或者不循环2.4 无头单向非循环链表和带头双向循环链表 3.单链表的实现3.1 准备工作3.2 节点的创建3.3 单链表的释放3.4 打印链表3.5 单链表的尾插3.6 单链表的尾删3.7 单链表头删3.8 单链…...

Python SciPy介绍

在数据科学和工程领域&#xff0c;Python已经成为了一个不可或缺的工具&#xff0c;这主要得益于其强大的库和框架支持。其中&#xff0c;SciPy库作为Python科学计算的核心库之一&#xff0c;为研究人员、工程师和数据分析师提供了大量高效的算法和数学工具。本文将带您深入了解…...

docker镜像源

1、直接在服务器上创建这个文件&#xff0c;将镜像源配置在里面 /etc/docker/daemon.json {"registry-mirrors": ["https://do.nark.eu.org","https://dc.j8.work","https://docker.m.daocloud.io","https://dockerproxy.com&qu…...

【clion】clion打开文件目录卡死问题

巨卡&#xff0c;几乎无法打开&#xff0c;据说是fsnotifier64.exe 被限制了。删除 火绒就好了。 关闭windows defender 官方&#xff1a;关闭 Windows 安全中心中的Defender 防病毒保护 此时&#xff0c;删除火绒&#xff1a; 界面变这样了&#xff1a;...

[CR]厚云填补_GridFormer

GridFormer: Residual Dense Transformer with Grid Structure for Image Restoration in Adverse Weather Conditions Abstract 恶劣天气条件下的图像恢复是计算机视觉中的一个难点。在本文中&#xff0c;我们提出了一种新的基于变压器的框架GridFormer&#xff0c;它可以作为…...

PostgreSQL数据库内核(二):通过initdb传递guc参数

目录 增加guc参数 initdb参数传递 pg_ctl参数传递 参数验证 新增guc参数pg_test_parameter&#xff0c;支持从initdb和pg_ctl命令中传递/覆盖参数&#xff0c;使用场景是TDE透明加密指定算法或者某些定制化需求。 增加guc参数 pg源码是这样描述guc参数的&#xff1a;它是全局…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...