生成分布式id

分布式系统中经常需要生成全局唯一 id ,要求:

  1. 全局唯一: 不能出现重复ID
  2. 高可用: 作为基础系统,被许多关键系统调用,一旦宕机,影响严重

在分布式系统中有很多的案例。

UUID

UUID 由算法生成,通常为36字节字符串表示。比如:

3A2504D0-4M89-11D3-9A0C-0305E82C3301

保证唯一性,根据不同的规范,定义不同位的值。可能包括MAC地址、时间戳、命名空间、随机数、时序等。

定义好规则后,可以直接由机器本地生成,相比其他来说不需要远程调用,使用方便。缺点是无法保证递增。

mysql 自增长

这个最早是 Flicker 采用的,基本所有聊到分布式 ID,都会说到这里。

思路是采取了mysql 的自增长 ID 的机制 ,(auto_increment + replace into)。

replace into 首先会尝试插入,如果存在会删除旧数据,插入新数据。

获取 ID :

1
2
REPLACE  INTO Tickets64(stub) values('a'); select last_insert_id(); 

避免单点故障,多个mysql 实例通过区分 auto_increment 的起始值和步长来生产 ID 。

优点:充分利用 mysql 的自增 id ,高可靠,有序

缺点:依赖数据库,性能可靠性取决于数据库。不好扩展。

snowflake

snowflake - 64bit Twitter的方案

41 位时间序列,精确到毫秒(可以使用69年)

10 位机器标示,(1024个节点)

12 位计数号 (每秒4096个ID)

优点: 整体递增,时间有序,高性能,可以根据业务灵活调整bit位划分

缺点: 依赖时钟,时间回拨可能导致重复 ID ,在分布式环境中非时间不一致导致非全局递增。

序列生成方式

  • 使用数据库同步ID
  • 每次取一定数量的可用 ID 在内存中,使用完后重新获取
  • 每个业务可以定义自己的序列名,隔离业务 。

优点: 大大降低数据库压力,生产 ID 数量大大提高,不同业务不影响

缺点: 依赖数据库

阿里的 tddl,美团的Leaf 都是这种思路 。

对于有些对 id 连续有要求的,可以根据每秒生成数做限制。比如4096个只使用其中的一部分,每次取前对id进行随机的跳跃。可以得到不连续的id。

思考

uuid 和 snowflake 的方案思路是一样的,只是一个是依赖机器,一个是依赖时间。 mysql 的方法是在没有解决方法的时候简单又行之有效的方法。

序列生成已经是很标准成熟的解决方案

  1. 依赖数据库,又不完全依赖数据库,数据库只是用来做持久化,用来做数据段的分配。
  2. 取出一段 id 后,不管业务怎么用,保证了 id 生成的效率
  3. 保证 id 是整体递增的
作者

张巍

发布于

2019-12-20

更新于

2019-12-20

许可协议

评论