常见分布式 ID 解决方案

分布式 ID 的生成是分布式系统中的一个核心问题,需要确保生成的 ID 全局唯一、性能高效,并且能够适应高并发和大规模的场景。以下是一些常见的分布式 ID 生成方案:

  1. UUID
  • 原理:UUID(Universally Unique Identifier)是一种通过一系列算法生成的128位数字,通常基于时间戳、计算机硬件标识符、随机数等元素。
  • 优点:实现简单,无需网络交互,保证全局唯一性。
  • 缺点:ID 较长(36个字符的字符串形式),可能导致存储和索引效率低下,且通常不能保证顺序性。
  • 适用场景:适用于对唯一性要求高,但对性能和存储空间要求不敏感的场景。
  1. NanoID
  • 原理:NanoID 是一个轻量级、安全、URL 友好的唯一字符串 ID 生成器。它使用加密安全的随机数生成器,确保生成的 ID 足够随机和安全。

    • 在 Java 中实现 NanoID,可以使用 jnanoid 库。
  • 优点

    • 短小精悍:生成的 ID 默认长度为 21 个字符,减少了存储空间的占用,提升了传输效率。

    • 安全性高:使用硬件随机数生成机制,借助 crypto moduleWeb Crypto API,确保生成的 ID 足够安全。

    • URL 友好:生成的 ID 只包含 URL 安全的字符,方便在 URL 中使用。

    • 性能优越:生成 ID 的速度非常快,比 UUID 快了约 60%。

    • 高度可定制:支持自定义 ID 的字母表和长度,灵活适配不同项目需求。

  • 缺点

    • 非人类可读:ID 不是连续的,可能使调试变得更加困难。
  • 适用场景

    • Web 应用程序:在 Web 开发中,NanoID 可以缩短 URL 长度,提升用户体验。

    • 短链服务:生成短小精悍的短链 ID,便于分享和记忆。

    • 分布式系统:在分布式环境中,用于节点间的消息标记。

    • API 令牌:安全地生成短期有效的 API 访问令牌。

  1. 数据库自增 ID
  • 原理:基于数据库的 auto_increment 自增 ID 可以生成分布式 ID。通过批量获取 ID 号段,减少对数据库的依赖。
    • 如果使用多个数据库,则将增长 ID 错开。
  • 优点:实现简单,ID 单调自增,数值类型查询速度快。
  • 缺点:在高并发场景下,单点数据库会成为性能瓶颈,且存在单点故障风险。
  • 适用场景:适用于对 ID 顺序性有要求,且并发量不高的场景。
  1. Redis 生成 ID
  • 原理:通过 Redis 的原子性 INCR 和 INCRBY 命令生成唯一的递增数值。
  • 优点:Redis 的高性能保证了即使在高负载下也能快速生成 ID。
  • 缺点:高度依赖网络,且需要额外的基础设施管理和维护。
  • 适用场景:适用于需要高并发生成 ID 的场景。
  1. Snowflake 算法
  • 原理:Snowflake 是 Twitter 开源的一种分布式 ID 生成算法,生成的是一个 64 位的长整型数字。通过组合时间戳、数据中心 ID、机器 ID 和序列号来确保 ID 的全局唯一性和趋势递增。
    • Mybatis-plus 可以使用 DefaultIdentifierGenerator 传入当前机器 IP 生成 workId 和 dataCenterId,但没有解决时钟回拨的问题。
  • 优点:不依赖数据库,适合分布式环境,生成 ID 的性能高。
  • 缺点强依赖机器时钟,如果机器时钟发生回拨,可能导致重复 ID
  • 适用场景:适用于需要全局唯一、递增 ID 的高并发分布式系统。
  1. Leaf
  • 原理:Leaf 是美团开源的分布式 ID 生成系统,提供了两种生成 ID 的方式:Leaf-segment 号段模式和 Leaf-snowflake 雪花算法。
    • Leaf-segment 号段模式:服务启动时从数据库获取一段 ID 号段并缓存到内存,之后直接从内存中分配 ID;当号段快用完时,异步从数据库获取新的号段,同时使用双 buffer 确保业务不受阻塞。
  • 优点:高性能、高可用、接入简单。
  • 缺点:依赖第三方组件如 ZooKeeper、MySQL。
  • 适用场景:适用于需要高可用性和高性能的分布式系统。
  1. UidGenerator
  • 原理:UidGenerator 是百度开源的基于 Snowflake 算法的分布式 ID 生成器,克服了雪花算法的并发限制。
    • 通过预生成一批唯一ID并缓存到RingBuffer中,避免了每次生成ID时对系统时钟的依赖,从而有效解决了雪花算法的时钟回拨问题。
    • 克服了雪花算法的并发限制
      • 借用未来时间:当当前秒内的 sequence 达到最大值时,UidGenerator 会借用未来的时间来生成新的 ID,从而突破了每秒生成 ID 数量的限制。
      • 使用 RingBuffer 缓存 ID:UidGenerator 采用 RingBuffer 来缓存已生成的 UID,通过并行化 UID 的生产和消费,提高了 ID 生成的效率。
      • 避免硬件级“伪共享”问题:通过对 CacheLine 补齐,避免了由 RingBuffer 带来的硬件级“伪共享”问题,进一步提升了性能
  • 优点:单个实例的 QPS 能超过 6000000。
  • 缺点:需要依赖 MySQL 来分配 WorkerId。
  • 适用场景:适用于高并发、高性能要求的分布式系统。
  1. TinyID
  • 原理:TinyID 是滴滴基于美团 Leaf 的号段模式基础上升级而来,支持数据库多主节点模式,并提供了 tinyid-client 客户端的接入方式。
  • 优点:支持多主节点模式,接入方便。
  • 缺点:依赖数据库。
  • 适用场景:适用于需要高可用性和扩展性的分布式系统。
  1. CosId
  • 原理:CosId 提供了通用、灵活、高性能的分布式 ID 生成器,包括 SnowflakeId、SegmentId 和 SegmentChainId 等多种生成方式。
    • SnowflakeId:
      • 当发生时钟回拨时会使用ClockBackwardsSynchronizer主动等待时钟同步来重新生成ID。
    • SegmentId:号段模式
      • SegmentId 每次从号段分发器获取一段连续的 ID 号段,并将其缓存到内存中,以减少对号段分发器的网络 IO 请求,从而提升性能。
      • 当内存中的号段即将耗尽时,需要同步地从号段分发器获取新的号段,这可能导致业务流程的短暂阻塞。
    • SegmentChainId:号段链模式
      • SegmentChainId 是 SegmentId 的增强版,通过 PrefetchWorker 提前获取新的号段,并维护一个安全距离,并支持基于饥饿状态的动态扩容/收缩安全距离。
      • 性能可达到近似 AtomicLong 的 TPS 性能
  • 优点:高性能,支持多种存储后端(如 Redis、Jdbc、Zookeeper、MongoDB 等)。
  • 缺点:需要根据具体存储后端进行配置和管理。
  • 适用场景:适用于需要高性能、高可用性的分布式系统。

总结比较

方案优点缺点
UUID代码实现简单、没有网络开销,性能好占用空间大、无序
数据库自增 ID实现简单、ID 自增有序并发性能受限、单点故障风险
Redis INCR性能优于数据库、ID 有序单点问题带来的数据一致性等问题
Snowflake 算法不依赖数据库等第三方系统,性能高时钟回拨可能导致重复 ID
NanoID短小精悍、安全性高、生成速度快、URL友好非人类可读、不连续
Leaf高性能、高可用、接入简单依赖第三方组件如 ZooKeeper、MySQL
UidGenerator单个实例的 QPS 能超过 6000000需要依赖 MySQL 来分配 WorkerId
TinyID支持多主节点模式,接入方便依赖数据库
CosId高性能,支持多种存储后端可以解决Snowflake 算法时钟回拨问题;需要根据具体存储后端进行配置和管理

根据实际需求选择合适的分布式 ID 生成方案,可以更好地满足系统的性能、可用性和扩展性要求。NanoID 凭借其超轻量级、安全性强、生成快速紧凑、兼容性佳以及高度可定制等诸多优势,在众多 ID 生成工具中脱颖而出,为开发者们提供了一种高效、可靠的解决方案。

Share this post:

Related content