首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一文了解分布式系统ID生成策略

一文了解分布式系统ID生成策略

作者头像
全菜工程师小辉
发布于 2021-06-25 12:53:50
发布于 2021-06-25 12:53:50
1.4K00
代码可运行
举报
运行总次数:0
代码可运行

在分布式系统中,经常需要对大量的数据、消息、http请求等进行唯一标识,例如链路追踪traceId、身份标识号、订单流水号、操作记录流水号、优惠券id等等。

这个时候数据库自增主键已经不能满足需求,需要一个能够生成分布式ID的系统。

分布式ID的特性

  1. 全局唯一。不能出现重复的ID,这是最基本的要求。
  2. 递增。递增有利于关系数据库索引性能。除了常见的连续递增,如1001,1002,1003等等,分布式ID还存在趋势递增的形式,即保证下一个ID大于上一个ID但不连续。这样的好处可以防止关键信息被泄露,例如toc业务中暴露给用户的ID,可能会暴露用户数量。(订单id同理)
  3. 高可用。为多个服务提供ID服务,一旦宕机,会造成严重影响。
  4. 好接入。秉着拿来即用的设计原则,接入文档要尽可能的简单。
  5. 高性能:必须要在压测下表现良好,如果达不到要求则在高并发环境下会导致系统瘫痪。
  6. 灵活多变:每个业务场景对ID的要求也各不相同,ID生成要做到灵活多变可配置,尽可能多的满足需求。

解决方案

1. UUID

UUID是Universally Unique Identifier的缩写,包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12包含36个字符的字符串,例如:321dsa13-das2-d231-gfdd-213as8asd899

UUID经由一定的算法机器生成,为了保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。

优点:

  1. 性能非常高,本地生成,没有网络消耗。
  2. 生成简单,没有高可用风险。
  3. 有利于信息安全,因为可读性差,无规律。

缺点:

  1. 太长,不易于存储。
  2. 无序,对MySQL索引不利,在InnoDB中,UUID的无序性可能会引起数据位置频繁变动,严重影响性能。
  3. UUID不能标识业务含义,可读性差。

2. 数据库自增 ID

利用数据库自增ID的特性来生成,如MySQL的auto_increment。其优点是数字类型,并且可以自增。当然缺点就是并发场景下的性能瓶颈。

优点:

  1. 简单,利用数据库自有功能实现。
  2. ID严格连续自增,可以实现一些对ID有特殊要求的业务。

缺点:

  1. 有重复发号的风险,例如MySQL数据库主从切换的场景。
  2. 发号性能限制于数据库性能。
  3. 强依赖数据库,当数据库异常时整个系统不可用。

进一步优化: 放弃主从复制的高可用架构,采用多主架构。每个主库设置不同的起始值和相同的步长,保证了号段的隔离。

3. Redis

Redis中的incr命令,可以实现原子自增。相比较数据库而言,Redis可支撑的并发量非常高,性能好。

但需要考虑下面两种情况造成的数据不一致问题:

  1. 宕机后重启恢复但存在未及时初始化。
  2. 主从切换,主从数据同步延迟。

优点:

  1. 简单,自有能力。
  2. 高并发环境下性能好,优于数据库。

缺点:

  1. 可能会重复发号。
  2. 需要保障Redis服务的高可用。

4. Zookeeper 实现

使用ZooKeeper作为分段节点协调工具,每台服务器首先从Zookeeper 获取一段号码,如[1,1000]的ID,此时Zookeeper上保存最大值 1000,每次获取的时候都会进行判断,如果ID <=1000,则更新本地的当前值,如果为1001,则会将Zookeeper 上的最大值更新至2000,本地缓存段更新为1001-2000,更新的时候使用分布式锁来实现。(相当于用Zookeeper实现了基于数据库的号段模式)

优点:

效率高。

缺点:

维护成本较高,不能同时满足多个系统对ID的需求,不够灵活。

5、基于数据库的号段模式

号段模式的思想是客户端每次从数据库中取出一批ID供程序使用,从表中获取本次ID值的范围,如[1,1000],然后客户端将申请的号段[1,1000]加载到内存。表结构参考如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE id_generator (
  id int(10) NOT NULL,
  max_id bigint(20) NOT NULL COMMENT '当前最大id',
  step int(20) NOT NULL COMMENT '号段的布长',
  biz_type    int(20) NOT NULL COMMENT '业务类型',
  version int(20) NOT NULL COMMENT '乐观锁版本号',
  PRIMARY KEY (`id`)
)

等这批号段ID用完,再次向数据库申请新号段,对max_id字段做一次update操作(update id_generator set max_id = #{max_id+step}, version = version + 1 where version = # {version} and biz_type = XXX),update成功则说明新号段获取成功,新的号段范围是(max_id ,max_id +step]

进一步优化:

  1. 在号段消耗一半的时候,提前预留下一段号段。将预留号段时机提前,减少阻塞发生概率。一般称此为双Buffer机制。
  2. 不同业务可以设置不同的生成规则。

5.雪花算法

雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。

雪花算法,不依赖其它系统或数据库,以服务的方式部署,供其它服务调用,稳定性高,生成 ID 的性能也非常高。

给每台机器分配一个唯一标识,然后通过下面的结构实现全局唯一ID:

  • 1位。未使用(二进制中最高位为1的都是负数,所以这个最高位固定是0)
  • 41位。毫秒级时间(41 位的长度可以使用 69 年)
  • 10位。包含5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点)
  • 12位。最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)

由于在Java中64bit的整数是long类型,所以在Java中SnowFlake算法生成的id就是long来存储的。

优点:

  1. 生成性能高。
  2. 整体上按照时间自增排序。

缺点:

  1. 强依赖机器时钟,如果时钟回拨,可能会导致服务异常。
  2. 不能同时满足多个系统对ID的需求,不够灵活。
  3. 在单机上是递增的,但是由于涉及到分布式环境,每台机器上的时钟不可能完全同步,会出现不是全局递增的情况。

6.Tinyid

Tinyid是滴滴开源的分布式ID生成方案,开源地址见于参考文档1,只提供基于号段模式来生成ID(加入了双Buffer机制)。

7.Uidgenerator

UidGenerator是由百度技术部开发,开源地址见于参考文档2,基于Snowflake实现的优化算法。借用未来时间和双Buffer来解决时间回拨与生成性能等问题,同时结合MySQL进行ID分配。

8.Leaf

Leaf是美团开源的分布式ID生成方案,开源地址见于参考文档3。提供两种生成的ID的方式:雪花算法模式和号段模式。可通过配置文件来指定。

Leaf的雪花算法模式依赖于ZooKeeper,其workId的生成策略是基于ZooKeeper的顺序ID来生成的;号段模式也是基于数据库的号段模式+双Buffer机制实现的。

参考文档:

  1. https://github.com/didi/tinyid
  2. https://github.com/baidu/uid-generator
  3. https://github.com/Meituan-Dianping/Leaf
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全菜工程师小辉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
分布式ID生成方案总结整理
对于单体系统来说,主键ID可能会常用主键自动的方式进行设置,这种ID生成方法在单体项目是可行的,但是对于分布式系统,分库分表之后,就不适应了,比如订单表数据量太大了,分成了多个库,如果还采用数据库主键自增的方式,就会出现在不同库id一致的情况,虽然是不符合业务的
SmileNicky
2022/11/02
3.2K0
分布式ID生成方案总结整理
常见分布式id生成方案_分布式id生成方案
在说分布式ID的具体实现之前,我们来简单分析一下为什么用分布式ID?分布式ID应该满足哪些特征?
全栈程序员站长
2022/11/18
1K0
常见分布式id生成方案_分布式id生成方案
9种分布式ID生成方式,总有一款适合你
业务量小于500W或数据容量小于2G的时候单独一个mysql即可提供服务,再大点的时候就进行读写分离也可以应付过来。但当主从同步也扛不住的是就需要分表分库了,但分库分表后需要有一个唯一ID来标识一条数据,数据库的自增ID显然不能满足需求;特别一点的如订单、优惠券也都需要有唯一ID做标识。此时一个能够生成全局唯一ID的系统是非常必要的。那么这个全局唯一ID就叫分布式ID。
sowhat1412
2020/11/05
1.3K0
9种分布式ID生成方式,总有一款适合你
一口气说出 9种 分布式ID生成方式,面试官有点懵了
前两天公众号有个粉丝给我留言吐槽最近面试:“四哥,年前我在公司受点委屈一冲动就裸辞了,然后现在疫情严重两个多月还没找到工作,接了几个视频面试也都没下文。好多面试官问完一个问题,紧接着说还会其他解决方法吗?能干活解决bug不就行了吗?那还得会多少种方法?”
程序员小富
2020/02/16
1.1K0
一口气说出 9种 分布式ID生成方式,面试官有点懵了
特好用!!!8种分布式ID生成方法
业务量小于500W或数据容量小于2G的时候单独一个mysql即可提供服务,再大点的时候就进行读写分离也可以应付过来。但当主从同步也扛不住的时候就需要分表分库了,但分库分表后需要有一个唯一ID来标识一条数据,且这个唯一ID还必须有规则,能辅助我们解决分库分表的一些问题。
公众号-Java编程大本营
2021/01/25
1.7K0
特好用!!!8种分布式ID生成方法
九种主流的分布式ID生成策略
构建分布式系统时,如何对数据进行唯一标识也是一个至关重要的设计。不仅要符合B-tree数据结构以维持查询性能,还要考虑唯一标识的连续性会不会影响系统安全性。在分库分表的情况下,还要避免唯一标识重复且高效等等需要考虑的点。为此,市场就出现了很多分布式ID生成方案。本文将详细介绍九种主流的分布式ID生成策略供大家参考使用。
王二蛋
2024/06/27
7090
为什么需要分布式ID?大厂的分布式 ID 生成方案是什么样的?| JavaGuide
今天分享一道朋友去京东面试真实遇到的面试题:“为什么要分布式ID?你项目中是怎么做的?”。
Guide哥
2021/06/25
2.2K0
带你了解「美团、百度和滴滴」的分布式 ID 生成系统
在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。如在美团点评的金融、支付、餐饮、酒店、猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一 ID 来标识一条数据或消息,数据库的自增 ID 显然不能满足需求;特别一点的如订单、骑手、优惠券也都需要有唯一 ID 做标识。此时一个能够生成全局唯一 ID 的系统是非常必要的。概括下来,那业务系统对 ID 号的要求有哪些呢?
CG国斌
2021/12/07
1.7K0
带你了解「美团、百度和滴滴」的分布式 ID 生成系统
分布式唯一 ID 生成方案浅谈
作者:shmilychen,腾讯 IEG 后台开发工程师 1. 分布式唯一 ID 特性 在业务开发中,会存在大量的场景都需要唯一 ID 来进行标识。比如,用户需要唯一身份标识;商品需要唯一标识;消息需要唯一标识;事件需要唯一标识等等。尤其是在分布式场景下,业务会更加依赖唯一 ID。 分布式唯一 ID 的特性如下: 全局唯一:必须保证生成的 ID 是全局性唯一的,这是分布式 ID 的基本要求; 有序性:生成的 ID 需要按照某种规则有序,便于数据库的写入和排序操作; 可用性:需要保证高并发下的可用性。除了对
腾讯技术工程官方号
2022/06/29
2.3K0
分布式唯一 ID 生成方案浅谈
这10种分布式ID,真香!
UUID (Universally Unique IDentifier) 通用唯一识别码 ,也称为 GUID (Globally Unique IDentifier) 全球唯一标识符。
苏三说技术
2024/09/18
4710
这10种分布式ID,真香!
分布式全局唯一ID生成方案(附源码)
Java中 JDK自带的 UUID产生方式就是版本4根据随机数生成的 UUID 和版本3基于名字的 UUID,有兴趣的可以去看看它的源码。
小熊学Java
2023/07/16
1.4K0
分布式全局唯一ID生成方案(附源码)
分布式系统ID的几种生成办法
一般单机或者单数据库的项目可能规模比较小,适应的场景也比较有限,平台的访问量和业务量都较小,业务ID的生成方式比较原始但是够用,它并没有给这样的系统带来问题和瓶颈,所以这种情况下我们并没有对此给予太多的关注。但是对于大厂的那种大规模复杂业务、分布式高并发的应用场景,显然这种ID的生成方式不会像小项目一样仅仅依靠简单的数据自增序列来完成,而且在分布式环境下这种方式已经无法满足业务的需求,不仅无法完成业务能力,业务ID生成的速度或者重复问题可能给系统带来严重的故障。所以这一次,我们看看大厂都是怎么分析和解决这种ID生成问题的,同时,我也将我之前使用过的方式拿出来对比,看看有什么问题,从中能够得到什么启发。
用户1214487
2020/06/19
6840
分布式系统ID的几种生成办法
技术总结|十分钟了解分布式系统中生成唯一ID
分布式系统中生成唯一ID在后台开发是经常遇到的架构设计,当然方案有很多,比如通过redis或者数据库实现自增。 但是如果依赖redis或者数据库,会导致单点问题,在架构上反而需要考虑点更多,那怎么解决呢?
用户1904552
2025/02/27
2140
技术总结|十分钟了解分布式系统中生成唯一ID
分布式唯一ID生成方案总结
在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。如在美团点评的金融、支付、餐饮、酒店、猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息,数据库的自增ID显然不能满足需求;特别一点的如订单、骑手、优惠券也都需要有唯一ID做标识。此时一个能够生成全局唯一ID的系统是非常必要的。
Bug开发工程师
2019/11/18
2K0
分布式ID生成方案总结
ID是数据的唯一标识,传统的做法是利用UUID和数据库的自增ID,在互联网企业中,大部分公司使用的都是Mysql,并且因为需要事务支持,所以通常会使用Innodb存储引擎,UUID太长以及无序,所以并不适合在Innodb中来作为主键,自增ID比较合适,但是随着公司的业务发展,数据量将越来越大,需要对数据进行分表,而分表后,每个表中的数据都会按自己的节奏进行自增,很有可能出现ID冲突。这时就需要一个单独的机制来负责生成唯一ID,生成出来的ID也可以叫做分布式ID,或全局ID。下面来分析各个生成分布式ID的机制。
macrozheng
2019/09/24
1K0
分布式ID生成方案总结
七种分布式全局 ID 生成策略,你更爱哪种?
松哥最近工作中刚好用到这块内容,于是调研了市面上几种常见的全局 ID 生成策略,稍微做了一下对比,供小伙伴们参考。
江南一点雨
2021/08/06
1K0
七种分布式全局 ID 生成策略,你更爱哪种?
分布式ID设计方案
oktokeep
2024/11/28
1330
9种分布式ID生成之 美团(Leaf)实战
前几天写过一篇《一口气说出 9种 分布式ID生成方式,面试官有点懵了》,里边简单的介绍了九种分布式ID生成方式,但是对于像美团(Leaf)、滴滴(Tinyid)、百度(uid-generator)都是一笔带过。而通过读者留言发现,大家普遍对他们哥三更感兴趣,所以后边会结合实战,详细的对三种分布式ID生成器学习,今天先啃下美团(Leaf)。
程序员小富
2020/02/28
3.4K0
9种分布式ID生成之 美团(Leaf)实战
分布式ID
生成足够简单,本地生成无网络消耗,具有唯一性,缺点:无序的字符串,不具备趋势自增特性,没有具体的业务含义,长度过长 16 字节 128 位,36 位长度的字符串,存储以及查询对 MySQL 的性能消耗较大,MySQL 官方明确建议主键要尽量越短越好,作为数据库主键 UUID 的无序性会导致数据位置频繁变动,严重影响性能
程序员NEO
2023/09/24
3090
分布式ID
那天,她终于给了我分布式ID的常用解决方案
🍁 作者:知识浅谈,CSDN签约讲师,CSDN原力作者,后端领域优质创作者,热爱分享创作 💒 公众号:知识浅谈 📌 擅长领域:后端全栈工程师、爬虫、ACM算法 🔥 联系方式vx:zsqtcc 她把分布式 ID 常见解决方案讲的真的透彻。 🤞这次都给他拿下🤞 为什么 分布式 ID 使用这么频繁呢? 这主要是因为大数据量,高并发使得单体数据库显得力不从心了。 正菜来了🛴🛴🛴 🍖基于sql数据库方案 🍕数据库主键自增 这种方式就比较简单直白了,就是通过关系型数据库的自增主键产生来唯一的 ID。
知识浅谈
2022/09/08
6200
相关推荐
分布式ID生成方案总结整理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验