分布式主键算法

目录

    • 一、引言
    • 二、常见算法介绍
      • 雪花算法(Snowflake Algorithm)
        • 特性
        • 详解
          • 优势
          • 劣势
      • UUID(Universally Unique Identifier)
        • 特性
        • 详解
          • 优势
          • 劣势
      • 数据库自增主键
        • 特性
        • 详解
          • 优势
          • 劣势
      • 分布式数据库的序列(Sequence)
        • 特性
        • 详解
          • 优势
          • 劣势
      • 基于数据库的分布式唯一ID生成服务
        • 特性
        • 详解
          • 优势
          • 劣势
    • 三、重点算法总结
      • 1.雪花算法详解
      • 2. 雪花算法的结构
      • 3. 雪花算法的工作原理
      • 4. 优点和限制
      • 5. 示例
      • 6. 总结

一、引言

   分布式主键算法的产生背景主要在于分布式系统的需求。在分布式系统中,由于多个节点同时进行操作,需要有一种机制来确保全局唯一性,避免发生冲突。这种机制就是分布式主键算法。
   在互联网行业中,新开的项目基本都需要进行分库分表,这就需要在不同的表或库中生成的ID都是全局唯一的。此外,对于大型互联网应用来说,除了数据库表的分片外,还需要考虑如何设计能支持高并发、高可用性的分布式系统。
   在这种情况下,分布式主键算法就变得非常重要。它们可以生成全局唯一的ID,这些ID不仅可以在多个表或库之间进行区分,还可以用于构建分布式系统的唯一标识符。

二、常见算法介绍

雪花算法(Snowflake Algorithm)

特性

简单高效:雪花算法是一种相对简单且高效的算法,易于实现。
全局唯一:生成的ID在分布式环境中是全局唯一的。
有序性:ID的生成是有序的,有助于提高数据库索引性能。

详解

   雪花算法将一个64位的整数ID分为三个部分:时间戳、机器ID和序列号。其中,时间戳占用了41位,机器ID占用了10位,序列号占用了12位。算法的工作原理如下:
   时间戳部分记录了生成ID的时间,通常是从系统启动时开始计算的毫秒数。这意味着雪花算法可以在69年内生成不重复的ID。
机器ID标识了不同的分布式节点,最多可以有1024个不同的节点。
   序列号部分用于确保在同一毫秒内生成的ID不会重复。如果在同一毫秒内生成多个ID,序列号部分会自增。
这三个部分的组合确保了雪花算法生成的ID在分布式环境中是唯一且有序的。

优势

高性能:雪花算法生成ID的性能很高,适用于高吞吐量的系统。
相对简单:算法本身相对简单,不需要依赖外部服务。

劣势

时钟同步性要求:算法依赖于时钟同步,如果系统时钟回退可能导致ID重复。
有限的机器ID数:机器ID的位数限制了可分配的机器数量。

UUID(Universally Unique Identifier)

特性

全球唯一:UUID是全球唯一的,不同系统生成的UUID也不会冲突。
分散性:UUID的生成不需要中心化控制,各个节点可以独立生成。

详解

   UUID是128位的全局唯一标识符,通常表示为36个字符的字符串。它的生成不依赖于中心化控制,可以在不同的系统中生成。UUID的生成通常基于随机数或基于MAC地址和时间戳等信息。由于其全局唯一性,UUID在跨系统集成和数据交换中很有用。

优势

全局唯一性:UUID在全球范围内保持唯一。
无需中心化服务:不需要依赖中心化的ID生成服务。

劣势

较大的存储空间:UUID通常是128位的,相比于64位的雪花ID,占用更多的存储空间。
不适合按时间排序:UUID的生成不依赖于时间戳,因此不适合按时间排序的场景。

数据库自增主键

特性

数据库依赖:生成主键依赖于数据库的自增主键机制。
顺序性:生成的主键是有序递增的,有助于提高数据库性能。

详解

   在关系型数据库中,可以使用自增主键列来生成唯一标识符。这种方法需要确保分布式系统中不同节点使用不同的数据库,并且需要数据库引擎的支持。数据库自增主键通常是整数或长整数,它们在插入新数据时会自动递增,保证了唯一性和顺序性。

优势

可靠性:数据库自增主键是数据库引擎控制的,保证了唯一性。
易于维护:不需要额外的分布式算法,易于维护和管理。

劣势

数据库压力:高并发情况下,数据库可能成为性能瓶颈。
不适用于多数据库:在多个数据库实例上生成唯一ID可能需要复杂的配置。

分布式数据库的序列(Sequence)

特性

数据库依赖:依赖于支持序列对象的分布式数据库。
顺序性:生成的序列号是有序的。

详解

   一些分布式数据库(如Oracle)支持序列对象,可以用来生成全局唯一的序列号。这种方法需要数据库的支持,并且需要确保分布式系统中的不同节点都能访问到同一数据库实例。序列号是由数据库引擎控制的,保证了唯一性和有序性。

优势

可靠性:分布式数据库控制序列的生成,保证唯一性。
适用于多数据库:可以在多个分布式数据库实例上使用。

劣势

数据库依赖性:需要依赖特定类型的分布式数据库。
配置复杂:配置和管理分布式数据库可能较为复杂。

基于数据库的分布式唯一ID生成服务

特性

高可用性:这些服务通常具有高可用性和容错性。
可配置性:可以根据需求配置不同的ID生成规则。

详解

   一些公司使用分布式的ID生成服务,例如Twitter的Snowflake服务或美团点评的Leaf服务。这些服务提供了高性能和高可用性的分布式ID生成,通常基于自定义的算法。

优势

高可用性:这些服务通常具有高可用性,不易发生单点故障。
高性能:专门优化的服务通常具有出色的性能。

劣势

引入外部依赖:需要依赖外部服务,增加了系统的复杂性。
配置和维护成本:需要配置和维护分布式ID生成服务。

三、重点算法总结

1.雪花算法详解

   雪花算法(Snowflake Algorithm)是一种用于分布式系统中生成唯一标识符的算法,由Twitter开发。它通过将一个64位的整数ID分为不同的部分,确保在分布式环境中生成的ID不会重复。本文将详细介绍雪花算法的工作原理和结构。

2. 雪花算法的结构

   雪花算法的生成的64位整数ID被分为三个部分,每一部分表示不同的信息,如下所示:
sql| 时间戳 (41位) | 机器ID (10位) | 序列号 (12位) |
以下是各个部分的详细解释:

  • 时间戳 (41位):时间戳占据了ID的高41位,通常是从系统启动开始计算的毫秒数。这意味着雪花算法可以在69年内生成不重复的ID(2^41毫秒约等于69年)。
  • 机器ID (10位):机器ID用于标识不同的分布式机器。每台机器都必须有一个唯一的机器ID,通常在部署前分配。这意味着最多可以有1024个不同的机器。
  • 序列号 (12位):序列号用于确保在同一毫秒内生成的ID不会重复。如果在同一毫秒内生成多个ID,序列号部分会自增,从0开始,最大可达4095。

3. 雪花算法的工作原理

雪花算法的工作原理如下:

  1. 当一个新的ID被生成时,算法会记录当前的时间戳(以毫秒为单位)。
  2. 如果当前时间与上次生成ID的时间相同,会在序列号部分自增。
  3. 如果序列号达到了最大值(4095),则会等待下一毫秒,以确保不会生成重复的ID。
  4. 如果当前时间与上次生成ID的时间不同,序列号重置为0。
  5. 然后,将各部分的值组合起来,生成一个64位的唯一ID。

4. 优点和限制

优点:

  • 全局唯一性:雪花算法生成的ID在分布式环境中是全局唯一的,不会发生重复。
  • 有序性:生成的ID具有有序性,有助于提高数据库检索性能。
  • 高性能:算法的实现相对简单,生成ID的性能很高。

限制:

  • 时钟同步性要求:雪花算法依赖于时钟同步,如果系统时钟回退可能会导致ID重复。
  • 有限的机器ID数:机器ID的位数限制了可分配的机器数量,最多只能有1024个不同的机器。
  • 时间戳回退限制:由于时间戳占据了41位,所以算法可以在2^41毫秒(约69年)内生成不重复的ID。如果系统运行时间超过了这个限制,可能需要额外的处理来防止时间戳回退问题。

5. 示例

以下是一个示例雪花ID的结构:
| 00011001010111011011001000101010011011111 | 0010101010 |110110000101 || 时间戳 (41位) | 机器ID (10位) | 序列号 (12位) |
   在示例中,时间戳部分占据了前41位,机器ID占据了接下来的10位,序列号占据了最后的12位。这三个部分共同组成了一个唯一的雪花ID。

以下是一个简单的Java实现雪花算法的例子:

public class SnowflakeIdGenerator {private final long epoch = 1629331200000L; // 2021-08-20 00:00:00private final int dataCenterIdBits = 5;private final int workerIdBits = 5;private final int sequenceBits = 12;private final int maxDataCenterId = ~(-1 << dataCenterIdBits);private final int maxWorkerId = ~(-1 << workerIdBits);private final int workerIdShift = sequenceBits;private final int dataCenterIdShift = sequenceBits + workerIdBits;private final int timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits;private final int sequenceMask = ~(-1 << sequenceBits);private final long dataCenterId;private final long workerId;private long sequence = 0L;private long lastTimestamp = -1L;public SnowflakeIdGenerator(long dataCenterId, long workerId) {if (dataCenterId > maxDataCenterId || dataCenterId < 0) {throw new IllegalArgumentException("Data center ID can't be greater than " + maxDataCenterId + " or less than 0");}if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException("Worker ID can't be greater than " + maxWorkerId + " or less than 0");}this.dataCenterId = dataCenterId;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) | (dataCenterId << dataCenterIdShift) | (workerId << workerIdShift) | sequence;}private long tilNextMillis(long lastTimestamp) {long timestamp = System.currentTimeMillis();while (timestamp <= lastTimestamp) {timestamp = System.currentTimeMillis();}return timestamp;}
}

在这个例子中,我们定义了一个SnowflakeIdGenerator类,该类具有nextId()方法,用于生成雪花ID。在构造函数中,我们需要传入数据中心ID和工作节点ID,它们是用来唯一标识每个雪花ID的。在nextId()方法中,我们首先获取当前时间戳,并检查它是否比上次生成ID的时间戳更大。如果是,则将序列号重置为0,并更新上次生成ID的时间戳。否则,我们将序列号递增,并检查是否超过了最大序列号。如果超过了最大序列号,则我们将时间戳递增到下一个毫秒。最后,我们将时间戳、数据中心ID、工作节点ID和序列号合并起来,得到最终的雪花ID。

6. 总结

   雪花算法是一种可靠且高效的分布式主键生成算法,已在实际生产中得到广泛应用。通过将时间戳、机器ID和序列号组合在一起,它确保了生成的ID在分布式环境中不会重复。雪花算法的全局唯一性和有序性使其成为分布式系统中的理想选择之一,特别适用于需要生成唯一标识符的场景。
点赞收藏,富婆包养✋✋

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

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

相关文章

【设计模式】六、建造者模式

文章目录 需求介绍角色应用实例建造者模式在 JDK 的应用和源码分析java.lang.StringBuilder 中的建造者模式 建造者模式的注意事项和细节 需求 需要建房子&#xff1a;这一过程为打桩、砌墙、封顶房子有各种各样的&#xff0c;比如普通房&#xff0c;高楼&#xff0c;别墅&…

【C语言次列车ing】No.1站---C语言入门

文章目录 前言一、什么是C语言二、第一个C语言程序三、数据类型四、变量、常量五、字符串转义字符注释 前言 &#x1f467;个人主页&#xff1a;小沈YO. &#x1f61a;小编介绍&#xff1a;欢迎来到我的乱七八糟小星球&#x1f31d; &#x1f4cb;专栏&#xff1a;C语言次列车i…

【笔试强训day02】倒置字符串 排序子序列

​&#x1f47b;内容专栏&#xff1a; 笔试强训集锦 &#x1f428;本文概括&#xff1a;C笔试强训day02。 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&#xff1a;2023.10.1 二、day02 1.倒置字符串 题目描述&#xff1a; 将一句话的单词进行倒置&…

手动实现BERT

本文重点介绍了如何从零训练一个BERT模型的过程&#xff0c;包括整体上BERT模型架构、数据集如何做预处理、MASK替换策略、训练模型和保存、加载模型和测试等。 一.BERT架构   BERT设计初衷是作为一个通用的backbone&#xff0c;然后在下游接入各种任务&#xff0c;包括翻译…

《MySQL高级篇》十六、主从复制

文章目录 1、主从复制概述1.1 如何提升数据库并发能力1.2 主从复制的作用 2、主从复制的原理2.1 原理剖析2.2 复制的基本原则 3、一主一从架构搭建3.1 准备工作3.2 主机配置文件3.3 从机配置文件3.4 主机&#xff1a;建立账户并授权3.5 从机&#xff1a;配置需要复制的主机3.6 …

面试记录_

1&#xff1a;面试杉岩数据&#xff08;python开发&#xff09; 1.1.1 选择题 for(int i0;i<n;i){for(int j0;j<n;jji) } }O(n) * (O(0) O(n/1) O(n/2) O(n/3) ... O(n/n)) 在最坏情况下&#xff0c;内部循环的迭代次数为 n/1 n/2 n/3 ... n/n&#xff0c;这是…

笔试强训Day8

链接&#xff1a;求最小公倍数__牛客网 T1:求最小公倍数 正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值&#xff0c;设计一个算法&#xff0c;求输入A和B的最小公倍数。 数据范围&#xff1a;1≤a,b≤100000 #include<iostream> using namespace…

【算法|贪心算法系列No.2】leetcode2208. 将数组和减半的最少操作次数

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

Unity把UGUI再World模式下显示到相机最前方

Unity把UGUI再World模式下显示到相机最前方 通过脚本修改Shader 再VR里有时候要把3D的UI显示到相机最前方&#xff0c;加个UI相机会坏事&#xff0c;可以通过修改unity_GUIZTestMode来解决。 测试用例 测试用例如下&#xff1a; 场景包含一个红色的盒子&#xff0c;一个UI…

MonkeyRunner自动化测试

一&#xff1a;简介 MonkeyRunner提供了一个API&#xff0c;使用此API写出的程序可以在Android代码之外控制Android设备和模拟器。通过monkeyrunner&#xff0c;您可以写出一个Python程序去安装一个Android应用程序或测试包&#xff0c;运行它&#xff0c;向它发送模拟击键&…

Linux C/C++下收集指定域名的子域名信息(类似dnsmap实现)

我们知道dnsmap是一个工具&#xff0c;主要用于收集指定域名的子域名信息。它对于渗透测试人员在基础结构安全评估的信息收集和枚举阶段非常有用&#xff0c;可以帮助他们发现目标公司的IP网络地址段、域名等信息。 dnsmap的操作原理 dnsmap&#xff08;DNS Mapping&#xff…

Xmake v2.8.3 发布,改进 Wasm 并支持 Xmake 源码调试

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它非常的轻量&#xff0c;没有任何依赖&#xff0c;因为它内置了 Lua 运行时。 它使用 xmake.lua 维护项目构建&#xff0c;相比 makefile/CMakeLists.txt&#xff0c;配置语法更加简洁直观&#xff0c;对新手非常友好&#x…

学信息系统项目管理师第4版系列14_沟通管理

1. 与IT项目成功有关的最重要的四个因素 1.1. 主管层的支持 1.2. 用户参与 1.3. 有经验的项目经理 1.4. 清晰的业务目标 1.5. 依赖于项目经理和团队具有良好的沟通能力 2. 沟通的主旨 2.1. 互动双方建立彼此相互了解的关系 2.2. 相互回应 2.3. 期待能经由沟通的行为与…

软件过程的介绍

软件过程概述 软件的诞生和生命周期是一个过程&#xff0c;我们总体上称这个过程为软件过程。软件过程是为了开发出软件产品&#xff0c;或者是为了完成软件工程项目而需要完成的有关软件工程的活动&#xff0c;每一项活动又可以分为一系列的工程任务。任何一个软件开发组织&a…

ESP32官方MPU6050组件介绍

前言 &#xff08;1&#xff09;因为我需要使用MPU6050的组件&#xff0c;但是又需要在这条I2C总线上挂载多个设备&#xff0c;所以我本人打算自己对官方的MPU6050的组件进行微调。建立一个I2C总线&#xff0c;设备依赖于这个总线挂载。 &#xff08;2&#xff09;既然要做移植…

【AI视野·今日Robot 机器人论文速览 第四十四期】Fri, 29 Sep 2023

AI视野今日CS.Robotics 机器人学论文速览 Fri, 29 Sep 2023 Totally 38 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;NCF,基于Neural Contact Fields神经接触场的方法实现有效的外部接触估计和插入操作。 (from FAIR ) 操作插入处理结果&am…

凉鞋的 Godot 笔记 101. Hello Godot!

101. Hello Godot 学习任何一门技术&#xff0c;第一件事就是先完成 Hello World&#xff01;的输出 所以我们也来先完成 Godot 的 Hello World。 我们所使用的 Godot 版本是 4.x 版本。 安装的过程就不给大家展示了&#xff0c;笔者更推荐初学者用 Steam 版本的 Godot&…

第一次作业题解

第一次作业题解 P5717 【深基3.习8】三角形分类 思路 考的是if()的使用,还要给三条边判断大小 判断优先级&#xff1a; 三角形&#xff1f;直角、钝角、锐角等腰等边 判断按题给顺序来 代码 #include <stdio.h> int main() {int a 0, b 0, c 0, x 0, y 0, z 0…

紫光同创FPGA图像视频采集系统,基于OV7725实现,提供工程源码和技术支持

目录 1、前言免责声明 2、设计思路框架视频源选择OV7725摄像头配置及采集动态彩条HDMA图像缓存输入输出视频HDMA缓冲FIFOHDMA控制模块HDMI输出 3、PDS工程详解4、上板调试验证并演示准备工作静态演示动态演示 5、福利&#xff1a;工程源码获取 紫光同创FPGA图像视频采集系统&am…

[每周一更]-(第64期):Dockerfile构造php定制化镜像

利用php官网镜像php:7.3-fpm&#xff0c;会存在部分插件缺失的情况&#xff0c;自行搭建可适用业务的镜像&#xff0c;才是真理 Dockerhub 上 PHP 官方基础镜像主要分为三个分支&#xff1a; cli: 没有开启 CGI 也就是说不能运行fpm。只可以运行命令行。fpm: 开启了CGI&#x…