一般情况下,会使用数据库的自增主键作为数据 ID,但是在大数量的情况下,我们往往会引入分布式、分库分表等手段来应对,很明显对数据分库分表后我们依然需要有一个唯一 ID 来标识一条数据或消息,数据库的自增 ID 已经无法满足需求。此时一个能够生成全局唯一 ID 的系统是非常必要的。

特点

  • 全局唯一性:不能出现重复的 ID 号,既然是唯一标识,这是最基本的要求。

  • 趋势递增单调递增:保证下一个 ID 一定大于上一个 ID。

  • 信息安全:如果 ID 是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定 URL 即可;如果是订单号就更危险了,竞对可以直接知道我们一天的单量。所以在一些应用场景下,会需要 ID 无规则、不规则。

常见方法介绍

UUID

UUID(Universally Unique Identifier)的标准型式包含 32 个 16 进制数字,以连字号分为五段,形式为 8-4-4-4-12 的 36 个字符,

示例:550e8400-e29b-41d4-a716-446655440000,到目前为止业界一共有 5 种方式生成UUID

优点:

性能非常高:本地生成,没有网络消耗。

缺点:

不易于存储:UUID 太长,16 字节 128 位,通常以 36 长度的字符串表示,很多场景不适用。

信息不安全:基于 MAC 地址生成 UUID 的算法可能会造成 MAC 地址泄露,

这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。

ID作为主键时在特定的环境会存在一些问题,比如做DB主键的场景下,UUID就非常不适用:

① MySQL官方有明确的建议主键要尽量越短越好[4],36个字符长度的UUID

不符合要求。

② 对 MySQL 索引不利:如果作为数据库主键,在 InnoDB 引擎下,UUID 的

无序性可能会引起数据位置频繁变动,严重影响性能。

雪花算法及其衍生

这种方案大致来说是一种以划分命名空间(UUID 也算,由于比较常见,所以单独分析)来生成 ID 的一种算法,Snowflake 是 Twitter 开源的分布式 ID 生成算法。Snowflake 把 64-bit 分别划分成多段,分开来标示机器、时间等,

比如在 snowflake 中的 64-bit 分别表示如下图所示:

第 0 位: 符号位(标识正负),始终为 0,没有用,不用管。

第 1~41 位 :一共 41 位,用来表示时间戳,单位是毫秒,可以支撑 2 ^41 毫秒(约 69 年)

第 42~52 位 :一共 10 位,一般来说,前 5 位表示机房 ID,后 5 位表示机器 ID(实际项目中可以根据实际情况调整),这样就可以区分不同集群/机房的节点,这样就可以表示 32 个 IDC,每个 IDC 下可以有 32 台机器。

第 53~64 位 :一共 12 位,用来表示序列号。 序列号为自增值,代表单台机器每毫秒能够产生的最大 ID 数(2^12 = 4096),也就是说单台机器每毫秒最多可以生成 4096 个 唯一 ID。

理论上 snowflake 方案的 QPS 约为 409.6w/s,这种分配方式可以保证在任何一个 IDC 的任何一台机器在任意毫秒内生成的 ID 都是不同的。

Snowflake 优缺点是:

优点:

毫秒数在高位,自增序列在低位,整个 ID 都是趋势递增的。

不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成 ID 的

性能也是非常高的。

可以根据自身业务特性分配 bit 位,非常灵活。

缺点:

强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不

可用状态。

当然,在我们自己的项目如果不想自行实现唯一性 ID,还可以利用外部中

间件,比如 Mongdb objectID,它也可以算作是和 snowflake 类似方法,通过“时

间+机器码+pid+inc”共 12 个字节,通过 4+3+2+3 的方式最终标识成一个 24 长度

的十六进制字符。

其次 Seata 内置了一个分布式 UUID 生成器,用于辅助生成全局事务 ID 和分

支事务 ID,我们同样可以拿来使用,完整类名为: io.seata.common.util.IdWorker

数据库生成

MYSQL

表设置自增主键

Oracle

使用sequence序列号

redis

Redis 的 incr 命令即可实现对 id 原子顺序递增,Redis 方案性能很好并且生成的 ID 是有序递增的。

不过,我们也知道,即使 Redis 开启了持久化,不管是快照(snapshotting,RDB)、只追加文件(append-only file, AOF)还是 RDB 和 AOF 的混合持久化依然存在着丢失数据的可能,那就意味着产生的 ID 存在着重复的概率。

文章作者: 刘同学
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 刘同学的小站
后端 算法
喜欢就支持一下吧