分布式ID(唯一性)的生成方法汇总

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 分布式ID(唯一性)的生成方法汇总

在软件研发工程中,经常会遇到系统主键的唯一性问题,尤其是在现如今比较火热的微服务架构中。分布式ID 具备唯一性、高可用性、有序增长等特性,其生成策略也较为复杂。


目前生成ID的方法多种多样,所适用的需求、场景及其性能也不尽相同。选择一种适合自己需求的解决方案是十分重要的。下面我们将对分布式系统下主键的生成策略总结一下,列举出其适用场景、优缺点等,为后续学习、工作提供参考。


1. JDK自带的UUID


程序设计语言开发工具包中都有生成主键的策略,以java语言的UUID为例(图1),它有着全球唯一的特性,可以做为分布式系统ID。核心思想是结合服务器的网卡、当地时间以及随记数来生成UUID。


  • 优点是生成简单、性能好、全球唯一,在数据迁移、系统合并或者数据库变更的情况下都可以应对。


  • 缺点就是生成的ID一般使用字符串存储,可读性性较差。在数据库中占有空间较大并且查询的效率比较低,在各微服务场景下,耗费的网络资源也响应增多。


image.png


2. 数据库自增ID


基于数据库的auto_increment自增ID完全可以充当分布式ID,具体原理:创建一个单独的实例用来生成ID,用一张数据表存储目前的最大ID(图2)。


当我们需要一个ID的时候,向表中插入一条记录返回主键ID,但访问量激增时数据库本身就是系统的瓶颈,用它来实现分布式服务风险比较大,不推荐!


  • 优点是数据库生成的ID绝对有序,高可用实现方式简单;


  • 缺点是需要独立部署数据库实例,成本高,数据库压力大,性能有限(可通过DB集群设置不同步长改善,即部署N台数据库实例,每台设置成不同的初始值,自增步长为机器的台数,如图3所示,可实现多个ID实例自增),但这种方法可能会导致数据的安全性问题。


image.png


3. 号段模式


一次按需批量生成多个ID,每次生成都需要访问数据库,将数据库修改为最大的ID值,并在内存中记录当前值及最大值一般可以借助redis实现,如图4所示。


  • 优点是避免了每次生成ID都要访问数据库并带来压力,提高性能;


  • 缺点是属于本地生成策略,存在单点故障,服务重启造成ID不连续。


image.png


4. Redis生成


Redis服务器来也可以生成全局ID,这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID 如图5。利用Redis的原子操作 INCR和INCRBY来实现。


  • 优点是不依赖于数据库,灵活方便,性能高。数字ID天然排序,对分页或者需要排序的结果很有帮助。使用Redis集群也可以防止单点故障的问题;


  • 缺点是依赖第三方组件Redis,增加系统复杂度。需要编码和配置的工作量比较大。


image.png


5. snowflake算法


snowflake 是 twitter 开源的分布式ID生成算法,其核心思想为,一个long型的ID:41 bit 作为毫秒数、10 bit 作为机器编号(10位的长度最多支持部署1024个节点)、12 bit 作为毫秒内序列号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号),如图6。


  • 优点是简单高效,生成速度快。时间戳在高位,自增序列在低位,整个ID是趋势递增的,按照时间有序递增。灵活度高,可以根据业务需求,调整bit位的划分,满足不同的需求。不需要其他依赖,使用方便。


  • 缺点是强依赖机器的时钟,如果服务器时钟回拨,会导致重复ID生成。在分布式环境上,每个服务器的时钟不可能完全同步,有时会出现不是全局递增的情况,不同机器配置不同worker id麻烦。


image.png


6. 百度UidGenerator


UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。UidGenerator以组件(图7)形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于docker等虚拟化环境下实例自动重启、漂移等场景。


  • 优点是全局唯一,高可用、高性能解决了始终回拨的问题;


  • 缺点是内置WorkerID分配器, 依赖数据库,启动阶段通过DB进行分配; 如自定义实现, 则DB非必选依赖。


image.png


7. 美团Leaf


美团的Leaf分布式ID生成组件(图8)是在Snowflake算法的基础上做了两套优化的方案:Leaf-segment数据库方案(相比之前的方案每次都要读取数据库,该方案改用代理服务器批量获取,且做了双缓存的优化)与Leaf-snowflake方案(主要针对时钟回拨问题做了特殊处理。若发生时钟回拨则拒绝发号,并进行告警)。


  • 优点是全局唯一,高可用、高性能用zookeeper解决了各个服务器时钟回拨的问题,弱依赖zookeeper;


  • 缺点是依赖第三方组件,如zookeeper。


image.png


8. zookeeper生成唯一ID


zookeeper主要通过其节点的信息来生成序列号,可以生成32位或者64位的数据版本号,客户端可以使用这个版本号来作为唯一的序列号。


  • 优点是实现原理较为简单,容易实现;


  • 缺点是需要依赖zookeeper,并且是多步调用API,如果在竞争较大的情况下,需要考虑使用分布式锁。因此,性能在高并发的分布式环境下,也不甚理想。


总的来看,目前的实现方案主要分为两种:


第一有中心(如数据库,包括mysql,redis等),其中可以会利用约束条件来实现集群(起始步长)。


第二种就是无中心,通过生成足够散落的数据,来确保无冲突(如UUID等)。


中心化方案的优点是ID数据长度相对小一些、数据可以实现自增趋势等;缺点是容易发生并发瓶颈、集群需要实现约定、横向扩展困难等。非中心化方案的优点是实现简单、不会出现中心节点带来的性能瓶颈、扩展性较高(扩展的局限往往集中于数据的离散问题);缺点是数据长度较长、无法实现数据的自增长。



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
20天前
|
机器学习/深度学习 分布式计算 算法
联邦学习是保障数据隐私的分布式机器学习方法
【6月更文挑战第13天】联邦学习是保障数据隐私的分布式机器学习方法,它在不暴露数据的情况下,通过在各设备上本地训练并由中心服务器协调,实现全局模型构建。联邦学习的优势在于保护隐私、提高训练效率和增强模型泛化。已应用于医疗、金融和物联网等领域。未来趋势包括更高效的数据隐私保护、提升可解释性和可靠性,以及与其他技术融合,有望在更多场景发挥潜力,推动机器学习发展。
27 4
|
19天前
|
存储 算法 Java
分布式唯一ID解决方案-雪花算法
分布式唯一ID解决方案-雪花算法
15 0
|
2月前
|
SQL 算法
基于若依的ruoyi-nbcio流程管理系统修改代码生成的sql菜单id修改成递增id(谨慎修改,大并发分布式有弊端)
基于若依的ruoyi-nbcio流程管理系统修改代码生成的sql菜单id修改成递增id(谨慎修改,大并发分布式有弊端)
39 1
|
2月前
|
调度
互动环境下分布式电源与电动汽车充电站的优化配置方法研究-全文复现matlab
互动环境下分布式电源与电动汽车充电站的优化配置方法研究-全文复现matlab
单向/双向V2G环境下分布式电源与电动汽车充电站联合配置方法(matlab代码)
单向/双向V2G环境下分布式电源与电动汽车充电站联合配置方法(matlab代码)
|
2月前
|
缓存 算法 关系型数据库
深度思考:雪花算法snowflake分布式id生成原理详解
雪花算法snowflake是一种优秀的分布式ID生成方案,其优点突出:它能生成全局唯一且递增的ID,确保了数据的一致性和准确性;同时,该算法灵活性强,可自定义各部分bit位,满足不同业务场景的需求;此外,雪花算法生成ID的速度快,效率高,能有效应对高并发场景,是分布式系统中不可或缺的组件。
308 2
深度思考:雪花算法snowflake分布式id生成原理详解
|
2月前
|
存储 SQL 算法
搞定了 6 种分布式ID,分库分表哪个适合做主键?
在《ShardingSphere5.x分库分表原理与实战》系列的第七篇文章中,作者探讨了分布式ID在分库分表中的重要性,以及如何利用`ShardingSphere-jdbc`的多种主键生成策略。文章介绍了`UUID`、`NanoID`、自定义雪花算法和`CosId`等策略的优缺点,并警告不要在SQL中手动拼接主键字段。此外,文章还展示了如何配置这些策略,并提醒读者`CosId`在5.2.0版本可能不可用。最后,文章讨论了如何自定义分布式主键生成算法,并强调选择策略时要考虑全局唯一性、性能和易用性。
303 1
|
2月前
|
调度
考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法(matlab代码)
考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法(matlab代码)
|
2月前
|
算法 关系型数据库 MySQL
Go语言中的分布式ID生成器设计与实现
【5月更文挑战第6天】本文探讨了Go语言在分布式系统中生成全局唯一ID的策略,包括Twitter的Snowflake算法、UUID和MySQL自增ID。Snowflake算法通过时间戳、节点ID和序列号生成ID,Go实现中需处理时间回拨问题。UUID保证全局唯一,但长度较长。MySQL自增ID依赖数据库,可能造成性能瓶颈。选择策略时需考虑业务需求和并发、时间同步等挑战,以确保系统稳定可靠。
132 0
|
2月前
|
算法 NoSQL Java
Java实战:分布式ID生成方案
在分布式系统的设计与开发过程中,如何生成全局唯一、有序且高可用的ID是一个绕不开的核心问题。尤其是在电商、社交网络、金融交易等领域,ID不仅是业务数据的重要标识,还可能直接影响系统的稳定性和扩展性。本文将深入剖析分布式ID生成方案的设计原则、常见算法,并通过Java示例展示一种可行的实现方式。
91 2