Maple's Blog.

唯一 ID 生成

字数统计: 732阅读时长: 2 min
2019/07/05

MySQL 自增 ID

优点:

  1. 自增数字
  2. 无需额外操作

缺点:

  1. 单点问题
    1. 可以设置 step 解决,例如一个表是 0, 2, 4 另个表是 1, 3, 5。但是这个方法后期扩展性差

UUID

v1() 真随机

v4() 伪随机

效率 v4() 远超 v1()

优点:

  1. 全世界唯一

缺点:

  1. 太长,做主键会降低性能,并且更多的容量
  2. 不能生成递增有序的数字
    1. 可以通过时间算法计算出时间戳
  3. mac 地址泄漏(?,没有查到这个事情)

Sequenece 表

根据一个唯一 table 值,插入 Sequence 表来获取 nextId()

优点:

支持多表

缺点:

  1. 所有表写入性能瓶颈取决于 Seqeuence 表的写入速度
  2. 单点问题(可以通过 主从同步 解决)
  3. 写入失败会造成 id 断层
  4. 如果遇到网络延迟可能会造成顺序不一致
  5. 请求两次 MySQL

Redis

redis.incr()

缺点:

多一个 redis 库。

snowflake

https://github.com/twitter/snowflake

1af4eb1ec81d4501a757cfdc9ada72d1

1. 第一位

占用1bit,其值始终是0,没有实际作用。

2. 时间戳

占用41bit,精确到毫秒,总共可以容纳约69 年的时间。

3. 工作机器id

占用10bit,其中高位5bit是数据中心ID(datacenterId),低位5bit是工作节点ID(workerId),做多可以容纳1024个节点。

4. 序列号

占用12bit,这个值在同一毫秒同一节点上从0开始不断累加,最多可以累加到4095。

SnowFlake算法在同一毫秒内最多可以生成多少个全局唯一ID呢?只需要做一个简单的乘法:

同一毫秒的ID数量 = 1024 X 4096 = 4194304

这个数字在绝大多数并发场景下都是够用的。

参考: <http://www.sohu.com/a/232008315_453160>

优点:

  1. 本地生成,不依赖数据库
  2. ID 递增趋势

缺点:

  1. 顺序依赖时钟
  2. 如果机器的系统时间在服务启动之后回拨,可能造成重复 ID

这边要注意一点是,workId 虽然字面上是工作机器 id。其实是相当于单个服务来说的。如果一个工作机器上同时部署多个服务,或者类似 node cluster 。则还需要分配 workId ,保证每个生产 id 的函数所持有的 workId 唯一。

Leaf 美团分布式 ID 生成服务

https://tech.meituan.com/2019/03/07/open-source-project-leaf.html

基于 ID 服务 (Leaf) 的 ID 生成。

在逻辑上将 id 段分成若干部分,多个 Leaf 服务通过读取 DB 获取长度相同的 id 段。在 id 用完时,主动再次获取,并将之前已经分配完的 id 段的最高的一个 id 持久化。

分发在内存中完成。

优点:

  1. 全局唯一
  2. client 不用生成 id
  3. 性能相对数据库较高

缺点:

  1. 要重新部署一套服务
  2. 相对本地生成 id 速度较慢
  3. client 获取 id 顺序无序【不能保证递增趋势】
CATALOG
  1. 1. MySQL 自增 ID
  2. 2. UUID
  3. 3. Sequenece 表
  4. 4. Redis
  5. 5. snowflake
  6. 6. Leaf 美团分布式 ID 生成服务