Skip to content

分布式 ID 生产策略

Zonglei Dong edited this page Jan 20, 2024 · 1 revision

UUID

UUID(Universally Unique Identifier)的标准形式包含32个16进制数字,以短划线(-)分为五段,形式为8-4-4-4-12的36个字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前为止业界一共有5种方式生成 UUID,详情参见 IETF 发布的UUID规范:A Universally Unique IDentifier (UUID) URN Namespace

  • 该方式优点:本地生成,性能非常高;无序(也可以算作优点)。
  • 该方式缺点:
    • 生成的 UUID 不适合做位数据库主键或者索引字段。生成的 UUID 长度长,无序。数据库索引一般是 B+树,无序数据相比于有序的数据,会导致更多次的页拆分,较长的数据也会导致索引页快速增长。
    • time-base 算法生成的 UUID 可能会存在 MAC 地址泄漏的安全风险。
  • 使用场景:非索引键 ID 生成,对性能要求较高,对顺序,长度没有较高要求的场景。

数据库自增主键

  • 优点:简单,满足有序递增。
  • 缺点:
    • 性能:每次生成 Sequence 都要从 DB(DataBase)获取,性能较差,存在单台 DB-Server 的读写瓶颈。
    • 可靠性:强依赖 DB,当 DB 异常时整个系统不可用。

Snowflake 和类 Snowflake

snowflake 是 Twitter 开源的分布式 ID 生成算法。

  • 优点:ID 都是趋势递增,生成性能高。
  • 缺点:强依赖机器时钟,如果机器上时钟回拨,会导致发号重复,需要解决时钟回拨问题。
  • 其他类似 MongoDB ObjectID 的类 Snowflake 算法,也具有同样的特点。
  • 使用场景:需要无序不被猜测的 ID,并且需要具备一定的高性能,可以使用 Snowflake 和类 Snowflake 算法。

ZooKeeper

ZooKeeper 这个方案用得较少,该方案严重依赖 ZooKeeper 集群,并且性能不是很高,不建议使用。

Redis

  • 优点:性能比数据库自增更优,能满足有序递增。
  • 缺点:由于 Redis 是内存的 KV 数据库,即使有 AOF 和 RDB,但是依然会存在数据丢失的可能性,有可能会造成 ID 重复。同时该方案强依赖于 Redis 集群的可用性。
  • 使用场景:不建议使用。

数据库号段模式

数据库号段模式在使用数据库的方案上,做了如下改变:每次获取一个 segment 号段(step决定号段大小)的值,使用之后再从数据库获取新的号段,可以极大减轻数据库的压力。方案还可以更加优化,过程中使用 segment cache,异步刷新 segment 来提高整体吞吐量。

  • 优点:相比数据库自增方案具有更高的性能和可用性。(可用性,即使 DB 故障关掉,segment cache 也可以持续使用一段时间)
  • 缺点:生成 ID 单调递增,ID 号码不够随机,可能会泄露发号数量的信息。仍然依赖于 DB 的可用性。
  • ZDAL Sequence 和美团 Leaf segment 模式采取的就是该方案。