分布式唯一ID
设计系统时,在具体设计领域实体(或描述对象属性详情的类)时需要设置一个ID,方便业务进行相关的处理。业务中不可避免的重复使用ID,因此ID生成策略非常重要。在生成时要求具有全局唯一性,生成效率高,并且生成ID值所占空间小,方便存储。全局唯一性 在分布式系统中尤为重要,如果控制不当,导致生成重复ID,则会出现业务数据串连,系统混乱。在查询时,要求快速从资源库中加载数据(资源库可以是数据库,文件等存储信息的辅助工具)。使用时,快速判断值是否相等或大小。
生成时:全局唯一性,高效生成,值不易太长,方便存储, 承递增趋势
查询时:通过ID快速查询实体数据
使用时:快速比较
目前常见有三种生成ID的方案:
自增ID: 数据库自增ID生成方式。数据库单表有性能瓶颈(数据库实例单表大概1k/sQPS量级,分布式系统一般要求达到1W/s QPS量级)。分库分表时,不同数据库设置不同的起始ID,然后设置相同的步长,达到分布式下ID唯一。如果前期预估步长太小,后期无法轻易添加新数据库实例,还会导致系统数据库性能瓶颈。如果预估步长太大,后期没有添加那么多机器,会导致ID部分序号浪费。Redis自增ID生成方式。依赖Reids中间件,不是所有系统都使用redis服务。自动ID一般都是int或long类型,长度短,非常方便存储。如果是使用数据库自增,生成效率非常高。当ID是聚簇索引时,查询效率非常高。
通过号段批量生成方式: 在数据表定义号序列ID的起始值,每次分配号段的长度(服务高峰期发号QPS的600倍(10分钟))。然后生成ID工具方法每次从数据库获取一个批次的号段,然后用于自增生成ID。用完再到数据库获取下个批次号段。通过分批次获取序列,可以降低数据访问频率,避免数据库性能瓶颈。需要定义生成规则,维护信息,有一定复杂度。其次,每次用完一个号段,都需要重新从数据库获取,会存在网络IO问题。可以优化成 双号段缓存策略。一个ID生成器,保存两个号段,第一个号段的序列使用了10%,即去获取第二个号段的数据。当第一个号段使用完后,切换到第二个号段。第二个号段使用10%后,再重新获取新的第二个号段。重复之前的步骤,这样就可以避免当前号段用完时,再从数据库去拿,出现网络IO等待。
当然,也可以用其它方式保存号段信息。但目前用数据库最方便,持久化最稳定。其它持久化可能没数据库安全稳定。成熟的方案有 滴滴(Tinyid),美团(Leaf-segment方案)。
根据时间和设备标识等生成唯一ID:这种方式无需依赖其它环境,生成效率高。行业有很多成熟方案。
①Java原生支持的UUID,是生成最快,效率最高的。但是生成的ID长度太长,不易保存。并且是无序的,数据库查询效率不高。可以用来作为业务唯一标识,但不适合做数据库聚簇索引的ID。
②雪花算法(snowflake):雪花算法是Twitter开源的一种高效,值空间小的ID生成方法。目前被互联网公司广泛使用,国内有它的衍生版百度(uid-generator),美团(Leaf-snowflake方案)。雪花算法通过定义64bit长度的数据不同区域标识不同信息,有效利用每bit内容,达到高效存储信息。
Snowflake ID组成结构:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特),总共64比特组成的一个Long类型。
第一个bit位(1bit):Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。
时间戳部分(41bit):毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始;
41位的时间戳可以使用69年,(1L << 41) / (1000L 60 60 24 365) = 69年
工作机器id(10bit):也被叫做workId,这个可以灵活配置,机房或者机器号组合都可以。
序列号部分(12bit),自增值支持同一毫秒内同一个节点可以生成4096个ID
③ Nano ID算法: 使用JavaScript 开发,一个小型、安全、对 URL 友好的唯一字符串 ID 生成器。 据作者说,比 uuid 更可靠和好用。Nano ID 值长度比UUID要短很多。
在具体设计系统时,没有固定不变策略。需要结合具体的业务场景,选择最合适的方法。在领域驱动设计中,实体ID 能表示业务场景唯一就行,可不用考虑ID自增情况。但实体保存时,需考虑后期查询使用的情况,所以此时非自增实体ID不适合做数据库表ID。在保存实体时,建议新增一个数据库表自增ID,作为聚簇索引,方便后续查询使用。同时相当于将资源属性和实体业务属性进行隔离,逻辑也更加清晰。
参考资料:
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通