您的位置:首页 > 编程语言 > Java开发

分布式 ID 生成策略 —— 听云资深 Java 工程师

2015-10-26 11:04 495 查看
本文截取自oschina的一篇讨论文章中“宇智波唐嫣”的发言,如果想查看整个讨论原文的,可访问原文,地址如下:http://www.oschina.net/question/865233_2137987?sort=default&p=1#answers

以下是“宇智波唐嫣”的发言

@Burn1ng1ce :先推荐你看 Instagram 的这篇 [0],他们要求生成
ID 尽量短而且可按生成时间排序,里面提到了好几种不同的 ID 生成方法的优缺点,比如:

在应用里面直接生成 UUID,优点是独立生成、性能好,缺点是生成的 ID 比较长。
单独运行一套 ID 生成服务,比如 Twitter 的 Snowflake [1],优点是可以生成比较短而且可以排序的 ID,并且分布式系统不容易挂,缺点是维护麻烦。

依赖数据库自增,比如 Flickr [2],优点是可以重用现有的计数,缺点是数据库写性能可能会是瓶颈,并且如果使用多个数据库,如何保证生成的 ID 可排序是个问题。
Instagram 然后根据自己的需要定制了基于 PostgreSQL 数据库的预分片 (pre-sharding) ID 生成机制。核心思想是预先分配足量的逻辑片 (logical shard),然后将大量的逻辑片映射到少量的物理片 (physical shard),最终依赖数据库的自增特性保证
ID 的唯一性。

注意以上提到的几套机制生成的都是 64 位的整数 ID,主要是给程序用来标记新建的数据对象用的。而原题目提到的用户 ID,我理解除了给程序用外,更重要的是要给人看。给人看的 ID 需要更加简短,因为对机器来说,64 位已经足够短了,而显然人是无法快速记忆 8744239352046571174
这样一长串数字的。所以生成给人看的 ID 需要根据应用场景尽可能短,比如绝大部分时候用户数量不会过亿,那么生成的 ID 的十进制表达最好不要超过 8 位数。

题目中要求的另外一点『不能直接看出规则』也是需要特别考虑的。对于中国互联网这样没有任何道德底限的地方来说尤为重要。原因大家都懂,如果 ID 是连续的,扒取内容的工作就非常简单了,直接按顺序下载指定的 URL 范围即可,爬虫都不用写了。所以对于公开 ID,不连续、无规则是基本要求。

以上两点和前述 Instagram 文章提到的几种 ID 生成需求有本质不同。结合知乎的用例,我把题目提到的这种 ID 需求特性概括为九个字:尽量短、无规则、无顺序。对于这样的应用场景,个人认为写一套单独的 ID 生成服务是比较好的办法。这个功能很简单,依赖过多的外部组件(如数据库)有点得不偿失。

目前我正在写的 ID 生成服务的基本思路是这样的:
ID 生成服务管理多个不同名字的 ID 池 (pool)。
每种不同类型的 ID 属于不同的 ID 池,比如知乎会有用户 ID 池、问题 ID 池、回答 ID 池等等。
每个 ID 池由多个定长 ID 块 (block) 构成。
每个 ID 块包含一段连续的 ID,比如第一块是从 0~1023,第二块从 1024~2047,以此类推。
每个 ID 块并不完全分配,而是按照一个给定的填充率 (fill ratio) 随机选择来分配,比如假设填充率是 50%,那么每个 ID 块中只有大约一半的 ID 会被分配。也就是说每个 ID 块是有随机空洞的。
如果某个 ID 块中可用 ID 被分配完毕,服务会自动生成下一个新的 ID 块,并按照填充率去掉不可用 ID。生成新的 ID 块时需要记录下最后一个 ID 块的起始 ID。
已经分配过的 ID 会写入一个 append-only 日志。新的 ID 块生成时会创建一个新的 append-only 日志(因为旧的已经不需要了)。
服务重新启动的时候先拿到最后一个 ID 块的起始 ID,再读取 append-only 日志将已经分配过的 ID 剔除,再剔除掉部分未分配的 ID 以维持填充率。
客户端发送请求访问 ID 生成服务。服务端返回 ID 做为回复。

优点是逻辑简单,生成的 ID 短小,单个进程维护起来方便。缺点是知道生成的 ID 的上限(可以用很大的块部分解决这个问题)。大概这样。欢迎讨论。

[0]: http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram
[1]: https://github.com/twitter/snowflake
[2]: http://code.flickr.com/blog/20
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MySQL 分布式ID