听说面试常考高性能分布式 ID 生成算法?

开发 前端
Twitter 的数据库经历了一个从小到大、从单机到分布式的增长过程。但无论在分布式数据库 Cassandra[3] 中,还是使用 gizzard[4] 方案水平扩容的多机 MySQL 中,都没有一个满足 Twitter 当时需求的全局 ID 生成方案。

分布式高性能 ID 生成算法——Snowflake ID。

维基百科 Snowflake ID 格式Untitled

来源:https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake[2]

雪花算法(Snowflake ID) 是时下应用相当广的一个分布式全序 ID 生成算法,这篇 Twitter 官方博客 2010 年的文章,宣告了雪花算法的诞生,概略的介绍了 Twitter 当时对分布式 ID 生产算法需求的背景(context)、可选项和最终方案。理解了其产生时的需求,也就理解了算法的一半,推荐一读。

问题背景。Twitter 的数据库经历了一个从小到大、从单机到分布式的增长过程。但无论在分布式数据库 Cassandra[3] 中,还是使用 gizzard[4] 方案水平扩容的多机 MySQL 中,都没有一个满足 Twitter 当时需求的全局 ID 生成方案。那 Twitter 当时对全局 ID 的要求是什么呢?

  • 每秒产生数万个 ID。这就限制了不能使用依赖多机沟通来产生 ID。毕竟一次网络通信延迟都会有 1ms+,自然难以实现超过 1k 的 qps。
  • 所有 ID 满足全序(roughly sortable)关系。即任意两个 id 都是可比的,毕竟 Feed 流中所有 Tweet 的排序都依赖此 ID。
  • 长度不超过 64 bit 。Twitter 以前经历过随着系统体量的增大而痛苦的增加 ID bit 数的过程,这次希望一步到位,但同时又不太长。

可选项。基于 MySQL 的自增 id,类似于 flickr[5]的方案。但不通过多机同步,难以提供全序保证。

一些现成的 UUID 算法,但其生成的 ID 都是 128 bit。

基于 Zookeeper 的全局自增 id 。自然,由于 Zab 等共识算法,其能保证全序,却不能满足 Twitter 的性能需求。

最终方案。通过组合时间戳、进程编号、自增序号,Twitter 找到了一种分布式高性能全序 ID 生成算法。基本思想是,大体保证机器间的时钟同步,并利用机器时钟生成时间戳作为自增 ID,如果两个进程产生了相同时间戳,则通过进程编号进一步确认其大小。由于一般时间戳会精确到毫秒,为了满足 QPS 需求,会留几位给自增 id,使得 1ms 内产生 10+ 个 id。

最终格式如上图,1 bit 的符号位,固定为0,以保证在有符号数体系下 ID 也为正数。41 bit 的时间戳,单位 ms,时间戳本身是个相对值,其起始点可以自行设置。10 bit 的进程编号,最终可支持含有 1024 个进程的单机或者集群,但一般来说,每个机器一个进程。12 bit 的自增序号,每毫秒最多允许产生 4k+ 个 ID。

在实际使用时,可以在保证总 bit 数的情况下,按需调整三个字段的 bit 数。比如进程数确定不会超过 100 个,则可以将对应字段缩短为 7 bit。进程序号可以在初始时通过一个全局发号器来分配,比如 Zookeeper。在之后的运行或者重启时,无需再改。

开源代码在此[6],其优点如下:

  • 高性能(Performance)。单进程 10k+ 的 QPS,平均 2ms 的延迟。
  • 无需沟通(Uncoordinated)。产生 ID 的这组进程,可以分布在多个数据中心的多个机器,而在产生数据时无需进行互相沟通(除了 NTP 时间戳同步)。
  • 大致按时间有序(Roughly Time Ordered)。可以从 ID 中解析出时间戳。
  • 可直接排序(Directly Sortable)。无需解析即可直接排序。
  • 紧凑(Compact)。不要 128 bit 就要 64 bit。
  • 高可用(Highly Available)。将进程分布在多数据中心的多台机器上,只要有一台机器活着,就仍能提供服务。

一些问题。雪花算法会隐式的依赖机器时钟,虽然并不严格。但使用者需要保证产生 ID 的所有机器通过 NTP 保持大致的时间同步。snowflake 算法可以处理由于 NTP 时钟同步带来的时钟回退问题。但解决方法很粗暴,即发现时钟回退了就死等到时钟超过上一次 ID 产生的对应时间点。也正因如此,需要维持所有机器时钟大致同步。

参考资料

[1]任何想法都欢迎来提 issue: https://github.com/DistSysCorp/ArticleListWeekly/issues

[2]Announcing Snowflake: https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake

[3]Cassandra: Open Source NoSQL Database: http://cassandra.apache.org/

[4]gizzard: http://github.com/twitter/gizzard

[5]Ticket Servers: Distributed Unique Primary Keys on the Cheap: https://code.flickr.net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/

[6]snowflake 2010: https://github.com/twitter-archive/snowflake/tree/snowflake-2010


责任编辑:武晓燕 来源: 木鸟杂记
相关推荐

2019-09-05 13:06:08

雪花算法分布式ID

2022-02-23 07:09:30

分布式ID雪花算法

2017-07-01 16:02:39

分布式ID生成器

2023-12-12 07:13:39

雪花算法分布式ID

2024-02-22 17:02:09

IDUUID雪花算法

2016-11-29 09:12:21

数据库分布式ID

2022-06-30 08:04:16

Redis分布式锁Redisson

2024-02-02 10:57:12

Java分布式算法

2021-07-06 10:35:46

分布式KafkaLinux

2024-10-07 08:52:59

分布式系统分布式 IDID

2022-12-08 08:13:11

分布式数据库CAP

2011-09-14 10:08:07

Beanstalkd

2023-11-10 08:22:09

雪花算法生成算法分布式

2012-12-28 17:31:06

2023-03-09 10:22:00

SpringBootRabbitMQ

2023-12-13 09:35:52

算法分布式

2022-06-16 07:31:15

MySQL服务器服务

2023-03-05 18:23:38

分布式ID节点

2023-11-14 08:24:59

性能Scylla系统架构

2019-09-12 08:50:37

Kafka分布式系统服务器
点赞
收藏

51CTO技术栈公众号