千家信息网

常见分布式唯一ID生成策略有哪些区别

发表于:2025-11-09 作者:千家信息网编辑
千家信息网最后更新 2025年11月09日,本篇内容介绍了"常见分布式唯一ID生成策略有哪些区别"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!简
千家信息网最后更新 2025年11月09日常见分布式唯一ID生成策略有哪些区别

本篇内容介绍了"常见分布式唯一ID生成策略有哪些区别"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

简单分析一下需求

所谓全局唯一的 id 其实往往对应是生成唯一记录标识的业务需求。

这个 id 常常是数据库的主键,数据库上会建立聚集索引(cluster index),即在物理存储上以这个字段排序。这个记录标识上的查询,往往又有分页或者排序的业务需求。所以往往要有一个time字段,并且在time字段上建立普通索引(non-cluster index)。

普通索引存储的是实际记录的指针,其访问效率会比聚集索引慢,如果记录标识在生成时能够基本按照时间有序,则可以省去这个time字段的索引查询。

这就引出了记录标识生成的两大核心需求:

  • 全局唯一

  • 趋势有序

常见生成策略的优缺点对比
方法一: 用数据库的 auto_increment 来生成

优点:

  • 此方法使用数据库原有的功能,所以相对简单

  • 能够保证唯一性

  • 能够保证递增性

  • id 之间的步长是固定且可自定义的
    缺点:

  • 可用性难以保证:数据库常见架构是 一主多从 + 读写分离,生成自增ID是写请求 主库挂了就玩不转了

  • 扩展性差,性能有上限:因为写入是单点,数据库主库的写性能决定ID的生成性能上限,并且 难以扩展
    改进方案:

  • 冗余主库,避免写入单点

  • 数据水平切分,保证各主库生成的ID不重复

如上图所述,由1个写库变成3个写库,每个写库设置不同的 auto_increment 初始值,以及相同的增长步长,以保证每个数据库生成的ID是不同的(上图中DB 01生成0,3,6,9…,DB 02生成1,4,7,10,DB 03生成2,5,8,11…)

改进后的架构保证了可用性,但缺点是

  • 丧失了ID生成的"绝对递增性":先访问DB 01生成0,3,再访问DB 02生成1,可能导致在非常短的时间内,ID生成不是绝对递增的(这个问题不大,目标是趋势递增,不是绝对递增

  • 数据库的写压力依然很大,每次生成ID都要访问数据库
    为了解决这些问题,引出了以下方法:

方法二:单点批量ID生成服务

分布式系统之所以难,很重要的原因之一是"没有一个全局时钟,难以保证绝对的时序",要想保证绝对的时序,还是只能使用单点服务,用本地时钟保证"绝对时序"。

数据库写压力大,是因为每次生成ID都访问了数据库,可以使用批量的方式降低数据库写压力。

如上图所述,数据库使用双master保证可用性,数据库中只存储当前ID的最大值,例如4。

ID生成服务假设每次批量拉取5个ID,服务访问数据库,将当前ID的最大值修改为4,这样应用访问ID生成服务索要ID,ID生成服务不需要每次访问数据库,就能依次派发0,1,2,3,4这些ID了。

当ID发完后,再将ID的最大值修改为11,就能再次派发6,7,8,9,10,11这些ID了,于是数据库的压力就降低到原来的1/6。

优点:

  • 保证了ID生成的绝对递增有序

  • 大大的降低了数据库的压力,ID生成可以做到每秒生成几万几十万个
    缺点:

  • 服务仍然是单点

  • 如果服务挂了,服务重启起来之后,继续生成ID可能会不连续,中间出现空洞(服务内存是保存着0,1,2,3,4,数据库中max-id是4,分配到3时,服务重启了,下次会从5开始分配,3和4就成了空洞,不过这个问题也不大)
    虽然每秒可以生成几万几十万个ID,但毕竟还是有性能上限,无法进行水平扩展

改进方案
  • 单点服务的常用高可用优化方案是"备用服务",也叫"影子服务",所以我们能用以下方法优化上述缺点:

如上图,对外提供的服务是主服务,有一个影子服务时刻处于备用状态,当主服务挂了的时候影子服务顶上。这个切换的过程对调用方是透明的,可以自动完成,常用的技术是 vip+keepalived。另外,id generate service 也可以进行水平扩展,以解决上述缺点,但会引发一致性问题。

方法三:uuid / guid

不管是通过数据库,还是通过服务来生成ID,业务方Application都需要进行一次远程调用,比较耗时。uuid是一种常见的本地生成ID的方法。

UUID uuid = UUID.randomUUID();

优点:

  • 本地生成ID,不需要进行远程调用,时延低

  • 扩展性好,基本可以认为没有性能上限
    缺点:

  • 无法保证趋势递增

  • uuid过长,往往用字符串表示,作为主键建立索引查询效率低,常见优化方案为"转化为两个uint64整数存储"或者"折半存储"(折半后不能保证唯一性)

方法四:取当前毫秒数

uuid是一个本地算法,生成性能高,但无法保证趋势递增,且作为字符串ID检索效率低,有没有一种能保证递增的本地算法呢?- 取当前毫秒数是一种常见方案。
优点:

  • 本地生成ID,不需要进行远程调用,时延低

  • 生成的ID趋势递增

  • 生成的ID是整数,建立索引后查询效率高
    缺点:

  • 如果并发量超过1000,会生成重复的ID

  • 这个缺点要了命了,不能保证ID的唯一性。当然,使用微秒可以降低冲突概率,但每秒最多只能生成1000000个ID,再多的话就一定会冲突了,所以使用微秒并不从根本上解决问题。

方法五:使用 Redis 来生成 id

当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR 和 INCRBY 来实现。
优点:

  • 依赖于数据库,灵活方便,且性能优于数据库。

  • 数字ID天然排序,对分页或者需要排序的结果很有帮助。
    缺点:

  • 如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。

  • 需要编码和配置的工作量比较大。

方法六:Twitter 开源的 Snowflake 算法

snowflake 是 twitter 开源的分布式ID生成算法,其核心思想为,一个long型的ID:

  • 41 bit 作为毫秒数 - 41位的长度可以使用69年

  • 10 bit 作为机器编号 (5个bit是数据中心,5个bit的机器ID) - 10位的长度最多支持部署1024个节点

  • 12 bit 作为毫秒内序列号 - 12位的计数顺序号支持每个节点每毫秒产生4096个ID序号

算法单机每秒内理论上最多可以生成1000*(2^12),也就是400W的ID,完全能满足业务的需求。

"常见分布式唯一ID生成策略有哪些区别"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

生成 数据 数据库 服务 保证 方法 缺点 性能 常见 索引 单点 优点 方案 算法 趋势 问题 需求 存储 分布式 上图 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 商友网络技术有限公司 供销社农产品供应数据库台帐表 东莞功能软件开发咨询 怎么删除一个编号的数据库 打印服务器系统 2021网络安全知识朝阳赛区 东南亚软件开发商 搭建http下载服务器 京东 淘宝 数据库设计 手机网络安全存在问题 计算机网络技术热门转业吗 自己家电脑怎么安装服务器系统 中移物联网 嵌入式软件开发 我的世界服务器密室杀手怎么进 怎么区分软件开发和销售 网络安全网络培训学校 神通数据库查看版本号 服务器维护表 有什么软件定时上传数据库到云端 软件开发的开发是什么意思 汕头教育软件开发定制 广州上座巴网络技术有限公司官网 信息网络安全的第三代是 学生网络安全保证书范文 青年网络安全公开课全集在线看 网络技术基础演示互动 网络技术系统构成 美国在线代理服务器网站 凤凰财经的数据库怎么进 软件开发工具的好处
0